Import Geant4 11.4.0.beta source tree
This commit is contained in:
@@ -6,7 +6,7 @@ It must **not** be used as a substitute for writing good git commit messages!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 2025-03-25 Ivana Hrivnacova (proccuts-V11-02-00)
|
||||
## 2025-03-25 Ivana Hrivnacova (proccuts-V11-03-00)
|
||||
- In G4ProductionCutsTable::UpdateCoupleTable:
|
||||
Make sure that the couple tables are updated if userEnergyCuts
|
||||
vectors are set
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
# Category decay History
|
||||
|
||||
See `CONTRIBUTING.rst` for details of **required** info/format for each entry,
|
||||
which **must** added in reverse chronological order (newest at the top).
|
||||
It must **not** be used as a substitute for writing good git commit messages!
|
||||
which **must** added in reverse chronological order (newest at the top). It must **not**
|
||||
be used as a substitute for writing good git commit messages!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 2025-04-03 Alvaro Tolosa-Delgado (decay-V11-02-00)
|
||||
## 2025-04-03 Alvaro Tolosa-Delgado (decay-V11-03-00)
|
||||
- Remove approximation in calculation of G4Decay path length, fix issue #2645
|
||||
|
||||
## 2021-12-10 Ben Morgan (decay-V11-00-00)
|
||||
|
||||
@@ -6,7 +6,56 @@ It must **not** be used as a substitute for writing good git commit messages!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 2025-01-14 Ben Morgan (emdna-V11-02-18)
|
||||
## 2025-05-28 Hoang Tran (emdna-V11-03-12)
|
||||
- Fixed COVERTY issues on new moleculecounter imple
|
||||
|
||||
## 2025-05-20 Hoang Tran (emdna-V11-03-11)
|
||||
- Fixed FPE on G4ChemReboundTransportation::calculateNextCoordinate
|
||||
|
||||
## 2025-05-19 Vladimir Ivanchenko (emdna-V11-03-10)
|
||||
- G4DNARuddIonisationModel, G4DNABornIonisationModel1, G4DNABornIonisationModel2
|
||||
fixed definition of the stationary code via G4EmParameters
|
||||
|
||||
## 2025-05-05 Hoang Tran (emdna-V11-03-09)
|
||||
- Replaced the shared_ptr with unique_ptr and raw for manager counters.
|
||||
|
||||
## 2025-04-23 Hoang Tran (emdna-V11-03-08)
|
||||
- Replaced the G4MoleculeCounter singleton with G4MoleculeCounterManager for managing counters.
|
||||
|
||||
## 2025-04-17 Vladimir Ivanchenko (emdna-V11-03-07)
|
||||
- G4DNARuddIonisationDynamicModel - disable atomic deexcitation in stationary
|
||||
mode, use G4VSItegration as a base class.
|
||||
- G4DNABornIonisationModel - new implementation of the Born model using
|
||||
G4DNASamplingTable class, use stationary and fast flags from EM parameters.
|
||||
- G4DNABornIonisationModel1 - use stationary and fast flags from EM parameters.
|
||||
- G4DNASamplingTable - new class allowing share sampling data between threads.
|
||||
|
||||
## 2025-04-01 Hoang Tran (emdna-V11-03-06)
|
||||
- update IRT-syn model for high LET applications.
|
||||
- Correct the G4DNAScavengerProcess for IRT-syn model
|
||||
- Created G4ChemReboundTransportation to handle the rebound
|
||||
transportation of the molecule.
|
||||
|
||||
## 2025-03-31 Hoang Tran (emdna-V11-03-05)
|
||||
- G4PhysChemIO - removed G4Analysis class and G4analysismng module
|
||||
dependency from G4emdna-utils
|
||||
|
||||
## 2025-03-12 Vladimir Ivanchenko (emdna-V11-03-04)
|
||||
- G4DNARuddIonisationDynamicModel - minor fix for alpha particles
|
||||
|
||||
## 2025-02-26 Vladimir Ivanchenko (emdna-V11-03-03)
|
||||
- G4DNARuddIonisationModel - added forgotten definition of stationary mode.
|
||||
|
||||
## 2025-02-24 Vladimir Ivanchenko (emdna-V11-03-02)
|
||||
- G4DNARuddIonisationDynamicModel - use G4Track and not G4DynamicParticle, allow
|
||||
to store radicals if chemistry is activated, update for ions with full electron
|
||||
shell
|
||||
|
||||
## 2025-02-12 Vladimir Ivanchenko (emdna-V11-03-01)
|
||||
- Added new G4DNARuddIonisationDynamicModel, which use charge from G4DynamicParticle.
|
||||
The model is applicable for all ions.
|
||||
|
||||
## 2025-01-14 Ben Morgan (emdna-V11-03-00)
|
||||
- Remove obsolete/commented references to G4AllocatorList.
|
||||
|
||||
## 2024-10-31 Hoang Tran (emdna-V11-02-17)
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
|
||||
// Author: Christian Velten (2025)
|
||||
|
||||
#ifndef G4MOLECULELOCATOR_HH
|
||||
#define G4MOLECULELOCATOR_HH 1
|
||||
#pragma once
|
||||
|
||||
#include "G4TouchableHandle.hh"
|
||||
#include "G4ThreadLocalSingleton.hh"
|
||||
|
||||
#include <memory>
|
||||
|
||||
class G4Track;
|
||||
class G4ITNavigator;
|
||||
|
||||
class G4MoleculeLocator final
|
||||
{
|
||||
friend class G4ThreadLocalSingleton<G4MoleculeLocator>;
|
||||
public:
|
||||
static G4MoleculeLocator* Instance();
|
||||
|
||||
~G4MoleculeLocator() = default;
|
||||
|
||||
private:
|
||||
G4MoleculeLocator();
|
||||
G4MoleculeLocator(const G4MoleculeLocator&) = delete;
|
||||
G4MoleculeLocator(G4MoleculeLocator&&) = delete;
|
||||
G4MoleculeLocator& operator=(const G4MoleculeLocator&) = delete;
|
||||
G4MoleculeLocator& operator=(G4MoleculeLocator&&) = delete;
|
||||
|
||||
G4ThreadLocalStatic G4MoleculeLocator* fpInstance;
|
||||
|
||||
G4bool fIsInitialized{false};
|
||||
std::unique_ptr<G4ITNavigator> fNavigator;
|
||||
|
||||
void Initialize();
|
||||
|
||||
public:
|
||||
void LocateMoleculeSetStateAndTouchable(G4Track*);
|
||||
G4TouchableHandle LocateMoleculeTrack(const G4Track*);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -186,6 +186,12 @@ class G4Scheduler : public G4VScheduler, public G4VStateDependent
|
||||
{
|
||||
fpUserScavenger = std::move(scavengerMaterial);
|
||||
}
|
||||
inline G4bool IsInteractionStep(){
|
||||
return fInteractionStep;
|
||||
}
|
||||
inline void SetInteractionStep(G4bool InteractionStep){
|
||||
fInteractionStep = InteractionStep;
|
||||
}
|
||||
|
||||
protected:
|
||||
void DoProcess();
|
||||
@@ -220,6 +226,7 @@ class G4Scheduler : public G4VScheduler, public G4VStateDependent
|
||||
G4bool fUseDefaultTimeSteps;
|
||||
G4double fTimeTolerance;
|
||||
G4double fGlobalTime;
|
||||
G4double fTmpGlobalTime;
|
||||
G4double fStartTime;
|
||||
G4double fStopTime;
|
||||
G4double fEndTime;
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
|
||||
#include "G4FastList.hh"
|
||||
#include "G4ManyFastLists.hh"
|
||||
#include "G4AllocatorList.hh"
|
||||
#include "G4Track.hh"
|
||||
#include "G4IT.hh"
|
||||
|
||||
|
||||
@@ -75,13 +75,20 @@ class G4VDNAMesh
|
||||
};
|
||||
struct hashFunc
|
||||
{
|
||||
size_t operator()(const Index& k) const
|
||||
{
|
||||
size_t h1 = std::hash<G4int>()(k.x);
|
||||
size_t h2 = std::hash<G4int>()(k.y);
|
||||
size_t h3 = std::hash<G4int>()(k.z);
|
||||
return (h1 ^ (h2 << 1)) ^ h3;
|
||||
}
|
||||
size_t operator()(const Index& k) const
|
||||
{
|
||||
size_t h1 = std::hash<G4int>()(k.x);
|
||||
size_t h2 = std::hash<G4int>()(k.y);
|
||||
size_t h3 = std::hash<G4int>()(k.z);
|
||||
|
||||
// Combine the hashes using a consistent and well-distributed technique
|
||||
size_t seed = 0;
|
||||
seed ^= h1 + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
seed ^= h2 + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
seed ^= h3 + 0x9e3779b9 + (seed << 6) + (seed >> 2);
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -78,6 +78,7 @@ geant4_add_module(G4emdna-man
|
||||
G4VUserBrownianAction.hh
|
||||
G4VDNAMesh.hh
|
||||
G4VUserPulseInfo.hh
|
||||
G4MoleculeLocator.hh
|
||||
SOURCES
|
||||
G4AllITFinder.cc
|
||||
G4ITBox.cc
|
||||
@@ -127,7 +128,8 @@ geant4_add_module(G4emdna-man
|
||||
G4VITTrackHolder.cc
|
||||
G4VScheduler.cc
|
||||
G4DNABoundingBox.cc
|
||||
G4VUserPulseInfo.cc)
|
||||
G4VUserPulseInfo.cc
|
||||
G4MoleculeLocator.cc)
|
||||
|
||||
geant4_module_link_libraries(G4emdna-man
|
||||
PUBLIC
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// Author: Christian Velten (2025)
|
||||
|
||||
#include "G4MoleculeLocator.hh"
|
||||
|
||||
#include "G4IT.hh"
|
||||
#include "G4ITTransportationManager.hh"
|
||||
#include "G4Track.hh"
|
||||
#include "G4TrackingInformation.hh"
|
||||
|
||||
G4ThreadLocal G4MoleculeLocator* G4MoleculeLocator::fpInstance = nullptr;
|
||||
|
||||
G4MoleculeLocator::G4MoleculeLocator()
|
||||
{
|
||||
fNavigator = std::make_unique<G4ITNavigator>();
|
||||
}
|
||||
|
||||
G4MoleculeLocator* G4MoleculeLocator::Instance()
|
||||
{
|
||||
if (fpInstance == nullptr) {
|
||||
static G4ThreadLocalSingleton<G4MoleculeLocator> instance;
|
||||
fpInstance = instance.Instance();
|
||||
}
|
||||
if (!fpInstance->fIsInitialized) {
|
||||
fpInstance->Initialize();
|
||||
}
|
||||
return fpInstance;
|
||||
}
|
||||
|
||||
void G4MoleculeLocator::Initialize()
|
||||
{
|
||||
fNavigator->SetWorldVolume(G4ITTransportationManager::GetTransportationManager()
|
||||
->GetNavigatorForTracking()
|
||||
->GetWorldVolume());
|
||||
fIsInitialized = true;
|
||||
}
|
||||
|
||||
G4TouchableHandle G4MoleculeLocator::LocateMoleculeTrack(const G4Track* pTrack)
|
||||
{
|
||||
G4IT* pITrack = GetIT(pTrack);
|
||||
|
||||
if (pITrack == nullptr) {
|
||||
G4Exception("G4MoleculeLocator::LocateMoleculeSetStateAndTouchable", "NOT_AN_IT", FatalErrorInArgument,
|
||||
"The track passed to this method appears to not hold an IT (molecule) object!");
|
||||
}
|
||||
|
||||
std::unique_ptr<G4ITNavigatorState_Lock> tmpStateHolder;
|
||||
if (pITrack->GetTrackingInfo()->GetNavigatorState() != nullptr)
|
||||
fNavigator->SetNavigatorState(pITrack->GetTrackingInfo()->GetNavigatorState());
|
||||
else {
|
||||
fNavigator->NewNavigatorState();
|
||||
tmpStateHolder = std::unique_ptr<G4ITNavigatorState_Lock>(fNavigator->GetNavigatorState());
|
||||
// will be deleted once method goes out of scope
|
||||
}
|
||||
|
||||
G4ThreeVector direction = pTrack->GetMomentumDirection();
|
||||
|
||||
fNavigator->LocateGlobalPointAndSetup(pTrack->GetPosition(), &direction, false, false);
|
||||
|
||||
G4TouchableHandle touchable = fNavigator->CreateTouchableHistory();
|
||||
return touchable;
|
||||
}
|
||||
|
||||
void G4MoleculeLocator::LocateMoleculeSetStateAndTouchable(G4Track* pTrack)
|
||||
{
|
||||
G4IT* pITrack = GetIT(pTrack);
|
||||
|
||||
if (pITrack == nullptr) {
|
||||
G4Exception("G4MoleculeLocator::LocateMoleculeSetStateAndTouchable", "NOT_AN_IT", FatalErrorInArgument,
|
||||
"The track passed to this method appears to not hold an IT (molecule) object!");
|
||||
}
|
||||
|
||||
fNavigator->NewNavigatorState();
|
||||
GetIT(pTrack)->GetTrackingInfo()->SetNavigatorState(fNavigator->GetNavigatorState());
|
||||
|
||||
G4ThreeVector direction = pTrack->GetMomentumDirection();
|
||||
|
||||
fNavigator->LocateGlobalPointAndSetup(pTrack->GetPosition(), &direction, false, false);
|
||||
|
||||
G4TouchableHandle touchable = fNavigator->CreateTouchableHistory();
|
||||
pTrack->SetTouchableHandle(touchable);
|
||||
pTrack->SetNextTouchableHandle(touchable);
|
||||
}
|
||||
@@ -155,6 +155,7 @@ void G4Scheduler::Create()
|
||||
fDefinedMinTimeStep = -1.;
|
||||
fReachedUserTimeLimit = false;
|
||||
fStopTime = -1.;
|
||||
fTmpGlobalTime = -1.;
|
||||
fpMessenger = new G4SchedulerMessenger(this);
|
||||
fReactionSet = G4ITReactionSet::Instance();
|
||||
fMaxTimeStep = DBL_MAX;
|
||||
@@ -378,6 +379,7 @@ G4double G4Scheduler::GetNextWatchedTime() const
|
||||
|
||||
void G4Scheduler::SynchronizeTracks()
|
||||
{
|
||||
fTmpGlobalTime = fGlobalTime;
|
||||
fGlobalTime = fTrackContainer.GetNextTime();
|
||||
G4double tmpGlobalTime = fGlobalTime;
|
||||
G4double nextWatchedTime = -1;
|
||||
@@ -499,7 +501,7 @@ void G4Scheduler::Stepping()
|
||||
fTSTimeStep = DBL_MAX;
|
||||
fILTimeStep = DBL_MAX;
|
||||
|
||||
fInteractionStep = false;
|
||||
//fInteractionStep = false;
|
||||
fReachedUserTimeLimit = false;
|
||||
|
||||
fITStepStatus = eUndefined;
|
||||
@@ -612,7 +614,7 @@ void G4Scheduler::Stepping()
|
||||
// Give the priority to the IL
|
||||
{
|
||||
fInteractionStep = true;
|
||||
fReactionSet->CleanAllReaction();
|
||||
//fReactionSet->CleanAllReaction();
|
||||
fTimeStep = fILTimeStep;
|
||||
fITStepStatus = eInteractionWithMedium;
|
||||
fpStepProcessor->PrepareLeadingTracks();
|
||||
|
||||
@@ -64,6 +64,8 @@ G4FastListNode<G4Track>* G4FastList<G4Track>::__GetNode(G4Track* __track)
|
||||
template<>
|
||||
void G4FastList<G4Track>::DeleteObject(G4Track* __track)
|
||||
{
|
||||
if (G4AllocatorList::GetAllocatorListIfExist() == nullptr) return;
|
||||
|
||||
auto __step = const_cast<G4Step*>(__track->GetStep());
|
||||
if (__step != nullptr)
|
||||
{
|
||||
|
||||
@@ -23,22 +23,125 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
/*
|
||||
* G4DNABornIonisationModel.hh
|
||||
*
|
||||
* Created on: 13 mai 2015
|
||||
* Author: matkara
|
||||
*/
|
||||
// Created 25.03.2025 V.Ivanchenko
|
||||
// on base of the G4DNABornIonisationModel1 of S.Incerti & M.Karamitros
|
||||
//
|
||||
// Simulation of ionisation for electrons and protons
|
||||
//
|
||||
|
||||
#ifndef SOURCE_PROCESSES_ELECTROMAGNETIC_DNA_MODELS_INCLUDE_G4DNABORNIONISATIONMODEL_HH_
|
||||
#define SOURCE_PROCESSES_ELECTROMAGNETIC_DNA_MODELS_INCLUDE_G4DNABORNIONISATIONMODEL_HH_
|
||||
#ifndef G4DNABornIonisationModel_h
|
||||
#define G4DNABornIonisationModel_h 1
|
||||
|
||||
#include "G4DNABornIonisationModel1.hh"
|
||||
#include "G4DNABornIonisationModel2.hh"
|
||||
#include "G4VEmModel.hh"
|
||||
#include "G4VSIntegration.hh"
|
||||
#include "G4ParticleChangeForGamma.hh"
|
||||
#include "G4DNAWaterIonisationStructure.hh"
|
||||
|
||||
class G4DNAChemistryManager;
|
||||
class G4VAtomDeexcitation;
|
||||
class G4DNACrossSectionDataSet;
|
||||
class G4DNASamplingTable;
|
||||
|
||||
class G4DNABornIonisationModel : public G4VEmModel, public G4VSIntegration
|
||||
{
|
||||
public:
|
||||
|
||||
G4DNABornIonisationModel(const G4ParticleDefinition* p = nullptr,
|
||||
const G4String& nam = "DNABornIonisationModel");
|
||||
|
||||
~G4DNABornIonisationModel() override;
|
||||
|
||||
void Initialise(const G4ParticleDefinition*, const G4DataVector&) override;
|
||||
|
||||
G4double ProbabilityDensityFunction(G4double ekin) 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;
|
||||
|
||||
void StartTracking(G4Track*) override;
|
||||
|
||||
void SelectFasterComputation(G4bool input) { fasterCode = input; };
|
||||
|
||||
void SelectStationary(G4bool input) { statCode = input; };
|
||||
|
||||
void SelectSPScaling(G4bool input) { spScaling = input; };
|
||||
|
||||
G4DNABornIonisationModel & operator=(const G4DNABornIonisationModel &right) = delete;
|
||||
G4DNABornIonisationModel(const G4DNABornIonisationModel&) = delete;
|
||||
|
||||
private:
|
||||
|
||||
void LoadData();
|
||||
|
||||
G4int SelectShell();
|
||||
|
||||
G4double SampleCumulative();
|
||||
|
||||
G4double SampleDifferential();
|
||||
|
||||
protected:
|
||||
|
||||
G4ParticleChangeForGamma* fParticleChangeForGamma;
|
||||
|
||||
private:
|
||||
|
||||
// Water density table
|
||||
static const std::vector<G4double>* fpWaterDensity;
|
||||
|
||||
// data
|
||||
static G4DNACrossSectionDataSet* xsdata_e;
|
||||
static G4DNACrossSectionDataSet* xsdata_p;
|
||||
G4DNACrossSectionDataSet* xsdata{nullptr};
|
||||
|
||||
// sampling data
|
||||
static G4DNASamplingTable* sampling_e;
|
||||
static G4DNASamplingTable* sampling_p;
|
||||
G4DNASamplingTable* sampling;
|
||||
|
||||
const G4ParticleDefinition* fParticle{nullptr};
|
||||
const G4Track* fTrack{nullptr};
|
||||
|
||||
G4DNAChemistryManager* fChemistry{nullptr};
|
||||
|
||||
// Deexcitation manager to produce fluo photons and e-
|
||||
G4VAtomDeexcitation* fAtomDeexcitation;
|
||||
|
||||
// limits of x-section table
|
||||
G4double fLowEnergy{0.0};
|
||||
G4double fHighEnergy{0.0};
|
||||
G4double fpLimitEnergy{0.0};
|
||||
G4double feLimitEnergy{0.0};
|
||||
|
||||
// tracking cut
|
||||
G4double fAbsorptionEnergy{0.0};
|
||||
|
||||
G4double fMass{0.0};
|
||||
G4double fPrimaryEnergy{0.0};
|
||||
G4double fMaxEnergy{0.0};
|
||||
G4double fTemp[5] = {0.0};
|
||||
|
||||
G4int fSelectedShell{0};
|
||||
G4int verbose{0};
|
||||
|
||||
G4bool isFirst{false};
|
||||
G4bool isInitialised{false};
|
||||
G4bool isElectron{false};
|
||||
G4bool fasterCode{false};
|
||||
G4bool statCode{false};
|
||||
G4bool spScaling{true};
|
||||
|
||||
// Final state
|
||||
G4DNAWaterIonisationStructure waterStructure;
|
||||
};
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
#ifndef G4DNABornIonisationModel
|
||||
#define G4DNABornIonisationModel G4DNABornIonisationModel1
|
||||
//#define G4DNABornIonisationModel G4DNABornIonisationModel2
|
||||
#endif
|
||||
|
||||
#endif /* SOURCE_PROCESSES_ELECTROMAGNETIC_DNA_MODELS_INCLUDE_G4DNABORNIONISATIONMODEL_HH_ */
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "G4VAtomDeexcitation.hh"
|
||||
#include "G4NistManager.hh"
|
||||
|
||||
class G4DNAChemistryManager;
|
||||
|
||||
class G4DNABornIonisationModel1 : public G4VEmModel
|
||||
{
|
||||
@@ -75,11 +76,12 @@ public:
|
||||
G4int /*level*/,
|
||||
const G4ParticleDefinition*,
|
||||
G4double /*kineticEnergy*/) override;
|
||||
|
||||
void StartTracking(G4Track*) override;
|
||||
|
||||
G4double DifferentialCrossSection(G4ParticleDefinition * aParticleDefinition, G4double k, G4double energyTransfer, G4int shell);
|
||||
|
||||
G4double TransferedEnergy(G4ParticleDefinition * aParticleDefinition,
|
||||
G4double incomingParticleEnergy, G4int shell, G4double random) ;
|
||||
G4double incomingParticleEnergy, G4int shell, G4double random);
|
||||
|
||||
inline void SelectFasterComputation(G4bool input);
|
||||
|
||||
@@ -93,28 +95,27 @@ protected:
|
||||
|
||||
private:
|
||||
|
||||
G4bool fasterCode;
|
||||
G4bool statCode;
|
||||
G4bool spScaling;
|
||||
G4bool fasterCode{false};
|
||||
G4bool statCode{false};
|
||||
G4bool spScaling{true};
|
||||
|
||||
// Water density table
|
||||
const std::vector<G4double>* fpMolWaterDensity;
|
||||
|
||||
// Deexcitation manager to produce fluo photons and e-
|
||||
G4VAtomDeexcitation* fAtomDeexcitation;
|
||||
G4VAtomDeexcitation* fAtomDeexcitation;
|
||||
|
||||
const G4Track* fTrack{nullptr};
|
||||
G4DNAChemistryManager* fChemistry{nullptr};
|
||||
|
||||
|
||||
std::map<G4String,G4double,std::less<G4String> > lowEnergyLimit;
|
||||
std::map<G4String,G4double,std::less<G4String> > highEnergyLimit;
|
||||
|
||||
// TODO :
|
||||
// std::map<const G4ParticleDefinition*,std::pair<G4double,G4double> > fEnergyLimits;
|
||||
|
||||
|
||||
G4bool isInitialised{false};
|
||||
G4int verboseLevel;
|
||||
|
||||
// Cross section
|
||||
|
||||
using MapFile = std::map<G4String, G4String, std::less<G4String>>;
|
||||
MapFile tableFile; // useful ?
|
||||
|
||||
@@ -163,29 +164,27 @@ private:
|
||||
VecMap eProbaShellMap[6]; // for cumulated dcs
|
||||
VecMap pProbaShellMap[6]; // for cumulated dcs
|
||||
|
||||
// Partial cross section
|
||||
|
||||
// Partial cross section
|
||||
G4int RandomSelect(G4double energy,const G4String& particle );
|
||||
|
||||
};
|
||||
|
||||
inline void G4DNABornIonisationModel1::SelectFasterComputation (G4bool input)
|
||||
{
|
||||
fasterCode = input;
|
||||
fasterCode = input;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
inline void G4DNABornIonisationModel1::SelectStationary (G4bool input)
|
||||
{
|
||||
statCode = input;
|
||||
statCode = input;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
inline void G4DNABornIonisationModel1::SelectSPScaling (G4bool input)
|
||||
{
|
||||
spScaling = input;
|
||||
spScaling = input;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
@@ -63,12 +63,13 @@ class G4DNAEventScheduler : public IEventScheduler
|
||||
G4DNAEventScheduler& operator=(const G4DNAEventScheduler& right) = delete;
|
||||
void Initialize(const G4DNABoundingBox& boundingBox, G4int pixel);
|
||||
void InitializeInMesh();
|
||||
void Voxelizing();
|
||||
void Voxelizing(const G4DNABoundingBox& boundingBox);
|
||||
void ReVoxelizing(G4int);
|
||||
void SetEndTime(const G4double&);
|
||||
G4double GetStartTime() const;
|
||||
G4double GetEndTime() const;
|
||||
G4double GetTimeStep() const;
|
||||
G4double GetGlobalTime() const;
|
||||
void SetStartTime(G4double time);
|
||||
|
||||
inline void SetVerbose(G4int verbose) { fVerbose = verbose; }
|
||||
@@ -93,7 +94,8 @@ class G4DNAEventScheduler : public IEventScheduler
|
||||
G4int GetPixels() const;
|
||||
void SetUserMeshAction(std::unique_ptr<G4UserMeshAction>);
|
||||
static G4bool CheckingReactionRadius(G4double resolution);
|
||||
|
||||
void ParticleBasedCounter();
|
||||
void ResetCounter();
|
||||
private:
|
||||
G4int fVerbose = 0;
|
||||
G4bool fInitialized = false;
|
||||
|
||||
+16
-10
@@ -38,6 +38,7 @@
|
||||
#include "G4ITTrackHolder.hh"
|
||||
#include "G4ITReaction.hh"
|
||||
#include "G4ReferenceCast.hh"
|
||||
#include <unordered_map>
|
||||
|
||||
class G4VDNAReactionModel;
|
||||
class G4DNAMolecularReactionTable;
|
||||
@@ -66,20 +67,19 @@ class G4DNAIndependentReactionTimeStepper : public G4VITTimeStepComputer
|
||||
G4VDNAReactionModel* GetReactionModel();
|
||||
|
||||
std::unique_ptr<G4ITReactionChange> FindReaction(
|
||||
G4ITReactionSet* pReactionSet, const G4double& currentStepTime = 0,
|
||||
const G4double& previousStepTime = 0,
|
||||
const G4bool& reachedUserStepTimeLimit = false);
|
||||
G4ITReactionSet* pReactionSet,
|
||||
G4double& currentStepTime,
|
||||
const G4double globalTime);
|
||||
void SetReactionProcess(G4VITReactionProcess* pReactionProcess);
|
||||
void SetVerbose(G4int);
|
||||
|
||||
private:
|
||||
void InitializeForNewTrack();
|
||||
class Utils;
|
||||
void CheckAndRecordResults(const Utils& utils);
|
||||
void CheckAndRecordResults(G4double reactionTime, const Utils& utils);
|
||||
|
||||
G4double GetTimeToEncounter(const G4Track& trackA, const G4Track& trackB);
|
||||
|
||||
G4bool fHasAlreadyReachedNullTime = false;
|
||||
const G4DNAMolecularReactionTable*& fMolecularReactionTable =
|
||||
reference_cast<const G4DNAMolecularReactionTable*>(fpReactionTable);
|
||||
G4VDNAReactionModel* fReactionModel = nullptr;
|
||||
@@ -88,18 +88,24 @@ class G4DNAIndependentReactionTimeStepper : public G4VITTimeStepComputer
|
||||
G4int fVerbose = 0;
|
||||
G4double fRCutOff = G4IRTUtils::GetRCutOff();
|
||||
G4VITReactionProcess* fpReactionProcess = nullptr;
|
||||
std::map<G4int, G4ThreeVector> fSampledPositions;
|
||||
std::vector<const G4Track *> fSecondaries;
|
||||
std::unordered_map<G4int, G4ThreeVector> fSampledPositions;
|
||||
std::set<G4int> fCheckedTracks;
|
||||
void InitializeReactions(G4double currentGlobalTime);
|
||||
G4bool fIsInitialized = false;
|
||||
G4double GetNextReactionTime();
|
||||
const G4ITReaction* GetNextReaction();
|
||||
|
||||
class Utils
|
||||
{
|
||||
public:
|
||||
Utils(const G4Track& tA, const G4Track& tB);
|
||||
~Utils() = default;
|
||||
const G4Track& fTrackA;
|
||||
const G4Track& fTrackB;
|
||||
const G4Molecule* fpMoleculeA;
|
||||
const G4Molecule* fpMoleculeB;
|
||||
|
||||
G4Track* fpTrackA{nullptr};
|
||||
G4Track* fpTrackB{nullptr};
|
||||
const G4Molecule* fpMoleculeA{nullptr};
|
||||
const G4Molecule* fpMoleculeB{nullptr};
|
||||
};
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -33,6 +33,7 @@ class G4DNAMolecularReactionTable;
|
||||
class G4VDNAReactionModel;
|
||||
class G4ITReactionSet;
|
||||
class G4VITTimeStepComputer;
|
||||
class G4DNAScavengerMaterial;
|
||||
|
||||
class G4DNAMakeReaction : public G4VITReactionProcess
|
||||
{
|
||||
@@ -59,5 +60,7 @@ protected:
|
||||
G4VDNAReactionModel* fpReactionModel;
|
||||
G4VITTimeStepComputer* fpTimeStepper;
|
||||
G4double fTimeStep;
|
||||
G4DNAScavengerMaterial* fpScavengerMaterial{nullptr};
|
||||
|
||||
};
|
||||
#endif
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// Created 11.02.2025 V.Ivanchenko & M. Vologzhin
|
||||
// on base of previous Rudd models
|
||||
//
|
||||
// Rudd model of ion ionisation using dynamic mass and charge of an ion
|
||||
//
|
||||
|
||||
#ifndef G4DNARuddIonisationDynamicModel_h
|
||||
#define G4DNARuddIonisationDynamicModel_h 1
|
||||
|
||||
#include "G4VEmModel.hh"
|
||||
#include "G4VSIntegration.hh"
|
||||
#include "G4ParticleChangeForGamma.hh"
|
||||
|
||||
#include "G4DNAWaterIonisationStructure.hh"
|
||||
#include <vector>
|
||||
|
||||
class G4DNAChemistryManager;
|
||||
class G4VAtomDeexcitation;
|
||||
class G4DNACrossSectionDataSet;
|
||||
class G4Pow;
|
||||
|
||||
class G4DNARuddIonisationDynamicModel : public G4VEmModel, public G4VSIntegration
|
||||
{
|
||||
public:
|
||||
|
||||
explicit G4DNARuddIonisationDynamicModel(const G4ParticleDefinition* p = nullptr,
|
||||
const G4String& nam = "DNARuddIonisationDynamicModel");
|
||||
|
||||
~G4DNARuddIonisationDynamicModel() override;
|
||||
|
||||
void Initialise(const G4ParticleDefinition*, const G4DataVector&) override;
|
||||
|
||||
G4double ProbabilityDensityFunction(G4double ekin) 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;
|
||||
|
||||
void StartTracking(G4Track*) override;
|
||||
|
||||
G4DNARuddIonisationDynamicModel & operator=
|
||||
(const G4DNARuddIonisationDynamicModel &right) = delete;
|
||||
G4DNARuddIonisationDynamicModel(const G4DNARuddIonisationDynamicModel&) = delete;
|
||||
|
||||
private:
|
||||
|
||||
void LoadData();
|
||||
|
||||
void SetParticle(const G4ParticleDefinition*);
|
||||
|
||||
G4int SelectShell();
|
||||
|
||||
G4double MaxEnergy();
|
||||
|
||||
G4double SampleElectronEnergy();
|
||||
|
||||
G4double CorrectionFactor();
|
||||
|
||||
G4double S_1s(G4double t,
|
||||
G4double energyTransferred,
|
||||
G4double slaterEffectiveChg,
|
||||
G4double shellNumber);
|
||||
|
||||
G4double S_2s(G4double t,
|
||||
G4double energyTransferred,
|
||||
G4double slaterEffectiveChg,
|
||||
G4double shellNumber);
|
||||
|
||||
|
||||
G4double S_2p(G4double t,
|
||||
G4double energyTransferred,
|
||||
G4double slaterEffectiveChg,
|
||||
G4double shellNumber);
|
||||
|
||||
G4double Rh(G4double t,
|
||||
G4double energyTransferred,
|
||||
G4double slaterEffectiveChg,
|
||||
G4double shellNumber);
|
||||
|
||||
protected:
|
||||
|
||||
G4ParticleChangeForGamma* fParticleChangeForGamma{nullptr};
|
||||
|
||||
private:
|
||||
|
||||
// Water density table
|
||||
static const std::vector<G4double>* fpWaterDensity;
|
||||
|
||||
// data for protons
|
||||
static G4DNACrossSectionDataSet* xsdata_hydrogen;
|
||||
static G4DNACrossSectionDataSet* xsdata_helium;
|
||||
static G4DNACrossSectionDataSet* xsdata_p;
|
||||
|
||||
// run time data
|
||||
G4DNACrossSectionDataSet* xsdata{nullptr};
|
||||
|
||||
const G4ParticleDefinition* fParticle{nullptr};
|
||||
const G4Track* fTrack{nullptr};
|
||||
|
||||
G4DNAChemistryManager* fChemistry{nullptr};
|
||||
G4Pow* fGpow;
|
||||
|
||||
//deexcitation manager to produce fluo photons and e-
|
||||
G4VAtomDeexcitation* fAtomDeexcitation{nullptr};
|
||||
|
||||
// low-energy limit of proton x-section table
|
||||
G4double fLowestEnergy{0.0};
|
||||
|
||||
// tracking cut
|
||||
G4double fAbsorptionEnergy{0.0};
|
||||
|
||||
G4double fMass{0.0};
|
||||
G4double fMassRate{1.0};
|
||||
G4double fScaledEnergy{0.0};
|
||||
|
||||
G4double slaterEffectiveCharge[3] = {0.0};
|
||||
G4double sCoefficient[3] = {0.0};
|
||||
G4double fTemp[5] = {0.0};
|
||||
|
||||
G4double F1{0.0};
|
||||
G4double F2{0.0};
|
||||
G4double alphaConst{0.0};
|
||||
G4double bEnergy{0.0};
|
||||
G4double u{0.0};
|
||||
G4double v{0.0};
|
||||
G4double wc{0.0};
|
||||
|
||||
G4int fSelectedShell{0};
|
||||
G4int verbose{0};
|
||||
|
||||
G4bool isFirst{false};
|
||||
G4bool isInitialised{false};
|
||||
G4bool isIon{false};
|
||||
G4bool isHelium{false};
|
||||
G4bool statCode{false};
|
||||
G4bool useDNAWaterStructure{true};
|
||||
|
||||
// energy levels of water molecule
|
||||
G4DNAWaterIonisationStructure waterStructure;
|
||||
};
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
#endif
|
||||
-2
@@ -71,8 +71,6 @@ public:
|
||||
G4double tmin,
|
||||
G4double maxEnergy) override;
|
||||
|
||||
void SelectStationary(G4bool val) { statCode = val; };
|
||||
|
||||
// method for unit tests
|
||||
G4double ComputeProbabilityFunction(const G4ParticleDefinition*, G4double kine,
|
||||
G4double deltae, G4int shell);
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
# Define the Geant4 Module.
|
||||
geant4_add_module(G4emdna-models
|
||||
PUBLIC_HEADERS
|
||||
G4ChemEquilibrium.hh
|
||||
G4DNABornAngle.hh
|
||||
G4DNABornExcitationModel.hh
|
||||
G4DNABornExcitationModel1.hh
|
||||
@@ -53,6 +52,7 @@ geant4_add_module(G4emdna-models
|
||||
G4DNARPWBAIonisationModel.hh
|
||||
G4DNARelativisticIonisationModel.hh
|
||||
G4DNARuddAngle.hh
|
||||
G4DNARuddIonisationDynamicModel.hh
|
||||
G4DNARuddIonisationExtendedModel.hh
|
||||
G4DNARuddIonisationModel.hh
|
||||
G4DNASancheExcitationModel.hh
|
||||
@@ -81,10 +81,10 @@ geant4_add_module(G4emdna-models
|
||||
G4VLEPTSModel.hh
|
||||
G4VUpdateSystemModel.hh
|
||||
SOURCES
|
||||
G4ChemEquilibrium.cc
|
||||
G4DNABornAngle.cc
|
||||
G4DNABornExcitationModel1.cc
|
||||
G4DNABornExcitationModel2.cc
|
||||
G4DNABornIonisationModel.cc
|
||||
G4DNABornIonisationModel1.cc
|
||||
G4DNABornIonisationModel2.cc
|
||||
G4DNACPA100ElasticModel.cc
|
||||
@@ -128,6 +128,7 @@ geant4_add_module(G4emdna-models
|
||||
G4DNARPWBAIonisationModel.cc
|
||||
G4DNARelativisticIonisationModel.cc
|
||||
G4DNARuddAngle.cc
|
||||
G4DNARuddIonisationDynamicModel.cc
|
||||
G4DNARuddIonisationExtendedModel.cc
|
||||
G4DNARuddIonisationModel.cc
|
||||
G4DNASancheExcitationModel.cc
|
||||
@@ -167,6 +168,7 @@ geant4_module_link_libraries(G4emdna-models
|
||||
G4emlowenergy
|
||||
G4emutils
|
||||
G4globman
|
||||
G4hepnumerics
|
||||
G4heprandom
|
||||
G4leptons
|
||||
G4materials
|
||||
|
||||
@@ -0,0 +1,386 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
|
||||
#include "G4DNABornIonisationModel.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4VAtomDeexcitation.hh"
|
||||
#include "G4UAtomicDeexcitation.hh"
|
||||
#include "G4LossTableManager.hh"
|
||||
#include "G4EmParameters.hh"
|
||||
#include "G4NistManager.hh"
|
||||
#include "G4DNACrossSectionDataSet.hh"
|
||||
#include "G4DNAChemistryManager.hh"
|
||||
#include "G4DNAMolecularMaterial.hh"
|
||||
#include "G4DNABornAngle.hh"
|
||||
#include "G4DNASamplingTable.hh"
|
||||
#include "G4LogLogInterpolation.hh"
|
||||
#include "G4DeltaAngle.hh"
|
||||
#include "G4Log.hh"
|
||||
#include "G4Exp.hh"
|
||||
#include "G4Electron.hh"
|
||||
#include "G4Proton.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DNACrossSectionDataSet* G4DNABornIonisationModel::xsdata_e = nullptr;
|
||||
G4DNACrossSectionDataSet* G4DNABornIonisationModel::xsdata_p = nullptr;
|
||||
G4DNASamplingTable* G4DNABornIonisationModel::sampling_e = nullptr;
|
||||
G4DNASamplingTable* G4DNABornIonisationModel::sampling_p = nullptr;
|
||||
const std::vector<G4double>* G4DNABornIonisationModel::fpWaterDensity = nullptr;
|
||||
|
||||
namespace
|
||||
{
|
||||
G4double scaleFactor = (1.e-22 / 3.343) * CLHEP::m*CLHEP::m;
|
||||
G4double tolerance = 10*CLHEP::eV;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DNABornIonisationModel::G4DNABornIonisationModel(const G4ParticleDefinition*,
|
||||
const G4String& nam) :
|
||||
G4VEmModel(nam)
|
||||
{
|
||||
SetDeexcitationFlag(true);
|
||||
|
||||
// Define default angular generator
|
||||
SetAngularDistribution(new G4DNABornAngle());
|
||||
|
||||
fasterCode = G4EmParameters::Instance()->DNAFast();
|
||||
|
||||
if (nullptr == xsdata_p) {
|
||||
isFirst = true;
|
||||
LoadData();
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DNABornIonisationModel::~G4DNABornIonisationModel()
|
||||
{
|
||||
if (isFirst) {
|
||||
delete xsdata_e;
|
||||
xsdata_e = nullptr;
|
||||
delete xsdata_p;
|
||||
xsdata_p = nullptr;
|
||||
delete sampling_e;
|
||||
sampling_e = nullptr;
|
||||
delete sampling_p;
|
||||
sampling_p = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNABornIonisationModel::LoadData()
|
||||
{
|
||||
// initialisation of static data once
|
||||
G4String fileElectron("dna/sigma_ionisation_e_born");
|
||||
xsdata_e = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor);
|
||||
xsdata_e->LoadData(fileElectron);
|
||||
|
||||
G4String fileProton("dna/sigma_ionisation_p_born");
|
||||
xsdata_p = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor);
|
||||
xsdata_p->LoadData(fileProton);
|
||||
|
||||
// to avoid possible threading problem fill this vector only once
|
||||
auto water = G4NistManager::Instance()->FindMaterial("G4_WATER");
|
||||
fpWaterDensity =
|
||||
G4DNAMolecularMaterial::Instance()->GetNumMolPerVolTableFor(water);
|
||||
|
||||
G4bool verb = true;
|
||||
sampling_e = new G4DNASamplingTable(100);
|
||||
sampling_p = new G4DNASamplingTable(100);
|
||||
|
||||
if (fasterCode) {
|
||||
G4String eb = "/dna/sigmadiff_cumulated_ionisation_e_born.dat";
|
||||
sampling_e->LoadData(eb, CLHEP::eV, 1.0, verb);
|
||||
G4String pb = "/dna/sigmadiff_cumulated_ionisation_p_born.dat";
|
||||
sampling_p->LoadData(pb, CLHEP::eV, 1.0, verb);
|
||||
} else {
|
||||
G4String eb = "/dna/sigmadiff_ionisation_e_born.dat";
|
||||
sampling_e->LoadData(eb, CLHEP::eV, scaleFactor, verb);
|
||||
G4String pb = "/dna/sigmadiff_ionisation_p_born.dat";
|
||||
sampling_p->LoadData(pb, CLHEP::eV, scaleFactor, verb);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNABornIonisationModel::Initialise(const G4ParticleDefinition* p,
|
||||
const G4DataVector&)
|
||||
{
|
||||
if (isInitialised) { return; }
|
||||
fParticleChangeForGamma = GetParticleChangeForGamma();
|
||||
isInitialised = true;
|
||||
|
||||
if (p == G4Electron::Electron()) {
|
||||
fParticle = p;
|
||||
xsdata = xsdata_e;
|
||||
sampling = sampling_e;
|
||||
fLowEnergy = 8*CLHEP::eV;
|
||||
fHighEnergy = 1*CLHEP::MeV;
|
||||
feLimitEnergy = 19*CLHEP::eV;
|
||||
fAbsorptionEnergy = 6*CLHEP::eV;
|
||||
fMass = CLHEP::electron_mass_c2;
|
||||
isElectron = true;
|
||||
} else if (p == G4Proton::Proton()) {
|
||||
fParticle = p;
|
||||
xsdata = xsdata_p;
|
||||
sampling = sampling_p;
|
||||
fLowEnergy = 100*CLHEP::keV;
|
||||
fHighEnergy = 100*CLHEP::MeV;
|
||||
fpLimitEnergy = 70*CLHEP::MeV;
|
||||
fAbsorptionEnergy = 50*CLHEP::eV;
|
||||
fMass = CLHEP::proton_mass_c2;
|
||||
isElectron = false;
|
||||
} else {
|
||||
G4ExceptionDescription ed;
|
||||
ed << "Born ionisation model is used for " << p->GetParticleName();
|
||||
G4Exception("G4DNABornIonisationModel::Initialise","em0003",
|
||||
FatalException, ed, " it is not available.");
|
||||
}
|
||||
verbose = G4EmParameters::Instance()->WorkerVerbose();
|
||||
|
||||
// defined stationary mode
|
||||
statCode = G4EmParameters::Instance()->DNAStationary();
|
||||
|
||||
// initialise atomic de-excitation
|
||||
if (!statCode)
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
|
||||
// chemistry
|
||||
auto chem = G4DNAChemistryManager::Instance();
|
||||
if (chem->IsChemistryActivated()) {
|
||||
fChemistry = chem;
|
||||
}
|
||||
|
||||
InitialiseIntegrator(0.1, 0.25, 1.05, 1*CLHEP::eV, 0.2*CLHEP::eV, 10*CLHEP::keV);
|
||||
if (verbose > 1) {
|
||||
G4cout << "Born ionisation model is initialized for "
|
||||
<< fParticle->GetParticleName() << G4endl;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNABornIonisationModel::StartTracking(G4Track* track)
|
||||
{
|
||||
fTrack = track;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DNABornIonisationModel::CrossSectionPerVolume(const G4Material* material,
|
||||
const G4ParticleDefinition*,
|
||||
G4double ekin, G4double, G4double)
|
||||
{
|
||||
// check if model is applicable for given material
|
||||
G4double density = (material->GetIndex() < fpWaterDensity->size())
|
||||
? (*fpWaterDensity)[material->GetIndex()] : 0.0;
|
||||
if (0.0 == density) { return 0.0; }
|
||||
|
||||
// check on kinetic energy (not scaled energy) to stop low-energy ion
|
||||
const G4double xSecMax = 1.e+10*CLHEP::barn;
|
||||
if (ekin < fAbsorptionEnergy) { return xSecMax; }
|
||||
|
||||
G4double e = std::min(ekin, fHighEnergy);
|
||||
G4double sigma = (e > fLowEnergy) ? xsdata->FindValue(e)
|
||||
: xsdata->FindValue(fLowEnergy) * e / fLowEnergy;
|
||||
|
||||
sigma *= density;
|
||||
|
||||
// ICRU49 electronic SP scaling - ZF, SI
|
||||
if (!isElectron && spScaling && e < fpLimitEnergy) {
|
||||
const G4double A = 1.39241700556072800000e-9;
|
||||
const G4double B = -8.52610412942622630000e-2;
|
||||
sigma *= G4Exp(A*(ekin/CLHEP::eV) + B);
|
||||
}
|
||||
if (verbose > 1) {
|
||||
G4cout << "G4DNABornIonisationModel for " << fParticle->GetParticleName()
|
||||
<< " Ekin(keV)=" << ekin/CLHEP::keV
|
||||
<< " sigma(cm^2)=" << sigma/CLHEP::cm2 << G4endl;
|
||||
}
|
||||
return sigma;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNABornIonisationModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
|
||||
const G4MaterialCutsCouple* couple,
|
||||
const G4DynamicParticle* dynParticle,
|
||||
G4double, G4double)
|
||||
{
|
||||
fPrimaryEnergy = dynParticle->GetKineticEnergy();
|
||||
// proton shoud be stopped - check on kinetic energy
|
||||
// electrons never have such low energy
|
||||
if (fPrimaryEnergy <= fAbsorptionEnergy) {
|
||||
fParticleChangeForGamma->SetProposedKineticEnergy(0.);
|
||||
fParticleChangeForGamma->ProposeTrackStatus(fStopButAlive);
|
||||
fParticleChangeForGamma->ProposeLocalEnergyDeposit(fPrimaryEnergy);
|
||||
return;
|
||||
}
|
||||
|
||||
fSelectedShell = SelectShell();
|
||||
G4double bindingEnergy = waterStructure.IonisationEnergy(fSelectedShell);
|
||||
|
||||
//SI: additional protection if tcs interpolation method is modified
|
||||
if (fPrimaryEnergy < bindingEnergy) { return; }
|
||||
|
||||
// compute max energy
|
||||
if (isElectron) {
|
||||
fMaxEnergy = 0.5*(fPrimaryEnergy - bindingEnergy);
|
||||
} else {
|
||||
G4double tau = fPrimaryEnergy/fMass;
|
||||
fMaxEnergy = 2.0*CLHEP::electron_mass_c2*tau*(tau + 2.0);
|
||||
}
|
||||
// SI: The following protection is necessary to avoid infinite loops :
|
||||
// e- ionisation cross section has non zero partial xs at 18 eV for shell 2.
|
||||
// e- has zero cumulated partial xs at 18 eV for shell 2.
|
||||
// This is due to the fact that the max allowed transfered energy is
|
||||
// (18+10.79)/2=17.025 eV and only transfered energies strictly above this
|
||||
// value have non zero partial cross section starting at transition energy 17.12 eV.
|
||||
if (fasterCode && isElectron && 2 == fSelectedShell && fPrimaryEnergy < feLimitEnergy) {
|
||||
do {
|
||||
fSelectedShell = SelectShell();
|
||||
} while (2 == fSelectedShell);
|
||||
}
|
||||
|
||||
G4double esec = fasterCode ? SampleCumulative() : SampleDifferential();
|
||||
G4double esum = 0.0;
|
||||
|
||||
// sample deexcitation
|
||||
// here we assume that H2O electronic levels are the same as Oxygen.
|
||||
// this can be considered true with a rough 10% error in energy on K-shell,
|
||||
G4int Z = 8;
|
||||
G4ThreeVector deltaDir =
|
||||
GetAngularDistribution()->SampleDirectionForShell(dynParticle, esec, Z,
|
||||
fSelectedShell,
|
||||
couple->GetMaterial());
|
||||
|
||||
// SI: only atomic deexcitation from K shell is considered
|
||||
if (fAtomDeexcitation != nullptr && fSelectedShell == 4) {
|
||||
auto as = G4AtomicShellEnumerator(0);
|
||||
auto ashell = fAtomDeexcitation->GetAtomicShell(Z, as);
|
||||
fAtomDeexcitation->GenerateParticles(fvect, ashell, Z, 0, 0);
|
||||
|
||||
// compute energy sum from de-excitation
|
||||
for (auto const & ptr : *fvect) {
|
||||
esum += ptr->GetKineticEnergy();
|
||||
}
|
||||
}
|
||||
// check energy balance
|
||||
// remaining excitation energy of water molecule
|
||||
G4double exc = std::max(bindingEnergy - esum, 0.0);
|
||||
|
||||
// remaining projectile energy
|
||||
G4double scatteredEnergy = fPrimaryEnergy - bindingEnergy - esec;
|
||||
if (scatteredEnergy < -tolerance || exc < -tolerance) {
|
||||
G4cout << "G4DNABornIonisationModel::SampleSecondaries: "
|
||||
<< "final E(keV)=" << scatteredEnergy/CLHEP::keV << " Ein(keV)="
|
||||
<< fPrimaryEnergy/CLHEP::keV << " " << fParticle->GetParticleName()
|
||||
<< " Edelta(keV)=" << esec/CLHEP::keV << " MeV, Exc(keV)=" << exc/CLHEP::keV
|
||||
<< G4endl;
|
||||
}
|
||||
scatteredEnergy = std::max(scatteredEnergy, 0.0);
|
||||
|
||||
// projectile
|
||||
if (!statCode) {
|
||||
fParticleChangeForGamma->SetProposedKineticEnergy(scatteredEnergy);
|
||||
fParticleChangeForGamma->ProposeLocalEnergyDeposit(exc);
|
||||
} else {
|
||||
fParticleChangeForGamma->SetProposedKineticEnergy(fPrimaryEnergy);
|
||||
fParticleChangeForGamma->ProposeLocalEnergyDeposit(fPrimaryEnergy - scatteredEnergy);
|
||||
}
|
||||
|
||||
// delta-electron
|
||||
auto dp = new G4DynamicParticle(G4Electron::Electron(), deltaDir, esec);
|
||||
fvect->push_back(dp);
|
||||
|
||||
// create radical
|
||||
if (nullptr != fChemistry) {
|
||||
fChemistry->CreateWaterMolecule(eIonizedMolecule, fSelectedShell, fTrack);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4int G4DNABornIonisationModel::SelectShell()
|
||||
{
|
||||
G4double sum = 0.0;
|
||||
G4double xs;
|
||||
G4double e = std::min(fPrimaryEnergy, fHighEnergy);
|
||||
for (G4int i=0; i<5; ++i) {
|
||||
auto ptr = xsdata->GetComponent(i);
|
||||
xs = (e > fLowEnergy) ? ptr->FindValue(e)
|
||||
: ptr->FindValue(fLowEnergy) * e/fLowEnergy;
|
||||
sum += xs;
|
||||
fTemp[i] = sum;
|
||||
}
|
||||
sum *= G4UniformRand();
|
||||
for (G4int i=0; i<5; ++i) {
|
||||
if (sum <= fTemp[i]) { return i; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4DNABornIonisationModel::SampleCumulative()
|
||||
{
|
||||
G4double e = sampling->SampleCumulative(fPrimaryEnergy, fSelectedShell);
|
||||
if (verbose > 1) {
|
||||
G4cout << "G4DNABornIonisationModel::SampleCumulative: "
|
||||
<< fParticle->GetParticleName()
|
||||
<< " Ekin(keV)=" << fPrimaryEnergy/CLHEP::keV
|
||||
<< " Ee(keV)=" << e/CLHEP::keV << G4endl;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4DNABornIonisationModel::SampleDifferential()
|
||||
{
|
||||
G4double xs = ComputeIntegral(0.0, fMaxEnergy);
|
||||
G4double e = (xs > 0.0) ? SampleValue() : G4UniformRand()*fMaxEnergy;
|
||||
if (verbose > 1) {
|
||||
G4cout << "G4DNABornIonisationModel::SampleDifferential: "
|
||||
<< fParticle->GetParticleName()
|
||||
<< " Ekin(keV)=" << fPrimaryEnergy/CLHEP::keV
|
||||
<< " Ee(keV)=" << e/CLHEP::keV << G4endl;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4DNABornIonisationModel::ProbabilityDensityFunction(G4double ekin)
|
||||
{
|
||||
return sampling->GetValue(fPrimaryEnergy, ekin, fSelectedShell);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4UAtomicDeexcitation.hh"
|
||||
#include "G4EmParameters.hh"
|
||||
#include "G4LossTableManager.hh"
|
||||
#include "G4DNAChemistryManager.hh"
|
||||
#include "G4DNAMolecularMaterial.hh"
|
||||
@@ -68,17 +69,7 @@ G4VEmModel(nam)
|
||||
// Define default angular generator
|
||||
SetAngularDistribution(new G4DNABornAngle());
|
||||
|
||||
// Selection of computation method
|
||||
|
||||
fasterCode = false;
|
||||
|
||||
// Selection of stationary mode
|
||||
|
||||
statCode = false;
|
||||
|
||||
// Selection of SP scaling
|
||||
|
||||
spScaling = true;
|
||||
fasterCode = G4EmParameters::Instance()->DNAFast();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
@@ -123,7 +114,7 @@ void G4DNABornIonisationModel1::Initialise(const G4ParticleDefinition* particle,
|
||||
G4String proton;
|
||||
|
||||
G4double scaleFactor = (1.e-22 / 3.343) * m*m;
|
||||
|
||||
|
||||
const char *path = G4FindDataDir("G4LEDATA");
|
||||
|
||||
// *** ELECTRON
|
||||
@@ -295,25 +286,36 @@ void G4DNABornIonisationModel1::Initialise(const G4ParticleDefinition* particle,
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
// Initialize water density pointer
|
||||
|
||||
if (isInitialised) { return; }
|
||||
fParticleChangeForGamma = GetParticleChangeForGamma();
|
||||
|
||||
// Initialize water density pointer
|
||||
fpMolWaterDensity = G4DNAMolecularMaterial::Instance()->
|
||||
GetNumMolPerVolTableFor(G4Material::GetMaterial("G4_WATER"));
|
||||
|
||||
// AD
|
||||
statCode = G4EmParameters::Instance()->DNAStationary();
|
||||
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
// AD
|
||||
if (!statCode)
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
|
||||
//
|
||||
|
||||
if (isInitialised)
|
||||
{ return;}
|
||||
fParticleChangeForGamma = GetParticleChangeForGamma();
|
||||
// chemistry
|
||||
auto chem = G4DNAChemistryManager::Instance();
|
||||
if (chem->IsChemistryActivated()) {
|
||||
fChemistry = chem;
|
||||
}
|
||||
isInitialised = true;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNABornIonisationModel1::StartTracking(G4Track* track)
|
||||
{
|
||||
fTrack = track;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DNABornIonisationModel1::CrossSectionPerVolume(const G4Material* material,
|
||||
const G4ParticleDefinition* particleDefinition,
|
||||
G4double ekin,
|
||||
@@ -450,20 +452,19 @@ void G4DNABornIonisationModel1::SampleSecondaries(std::vector<G4DynamicParticle*
|
||||
|
||||
G4int ionizationShell = 0;
|
||||
|
||||
if (!fasterCode) ionizationShell = RandomSelect(k,particleName);
|
||||
|
||||
// SI: The following protection is necessary to avoid infinite loops :
|
||||
// sigmadiff_ionisation_e_born.dat has non zero partial xs at 18 eV for shell 3 (ionizationShell ==2)
|
||||
// sigmadiff_cumulated_ionisation_e_born.dat has zero cumulated partial xs at 18 eV for shell 3 (ionizationShell ==2)
|
||||
// this is due to the fact that the max allowed transfered energy is (18+10.79)/2=17.025 eV and only transfered energies
|
||||
// strictly above this value have non zero partial xs in sigmadiff_ionisation_e_born.dat (starting at trans = 17.12 eV)
|
||||
|
||||
if (fasterCode)
|
||||
do
|
||||
{
|
||||
if (!fasterCode) {
|
||||
ionizationShell = RandomSelect(k,particleName);
|
||||
} while (k<19*eV && ionizationShell==2 && particle->GetDefinition()==G4Electron::ElectronDefinition());
|
||||
|
||||
} else {
|
||||
do {
|
||||
ionizationShell = RandomSelect(k,particleName);
|
||||
} while (k<19*eV && ionizationShell==2 && particle->GetDefinition()==G4Electron::ElectronDefinition());
|
||||
}
|
||||
G4double bindingEnergy = 0;
|
||||
bindingEnergy = waterStructure.IonisationEnergy(ionizationShell);
|
||||
|
||||
@@ -481,8 +482,6 @@ void G4DNABornIonisationModel1::SampleSecondaries(std::vector<G4DynamicParticle*
|
||||
{
|
||||
secondaryKinetic = RandomizeEjectedElectronEnergyFromCumulatedDcs(particle->GetDefinition(),k,ionizationShell);
|
||||
}
|
||||
//
|
||||
|
||||
G4int Z = 8;
|
||||
|
||||
G4ThreeVector deltaDirection =
|
||||
@@ -587,17 +586,10 @@ void G4DNABornIonisationModel1::SampleSecondaries(std::vector<G4DynamicParticle*
|
||||
fParticleChangeForGamma->ProposeLocalEnergyDeposit(k-scatteredEnergy);
|
||||
}
|
||||
|
||||
// TEST //////////////////////////
|
||||
// if (secondaryKinetic<0) abort();
|
||||
// if (scatteredEnergy<0) abort();
|
||||
// if (k-scatteredEnergy-secondaryKinetic-deexSecEnergy<0) abort();
|
||||
// if (k-scatteredEnergy<0) abort();
|
||||
/////////////////////////////////
|
||||
|
||||
const G4Track * theIncomingTrack = fParticleChangeForGamma->GetCurrentTrack();
|
||||
G4DNAChemistryManager::Instance()->CreateWaterMolecule(eIonizedMolecule,
|
||||
ionizationShell,
|
||||
theIncomingTrack);
|
||||
// create radical
|
||||
if (nullptr != fChemistry) {
|
||||
fChemistry->CreateWaterMolecule(eIonizedMolecule, ionizationShell, fTrack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -696,50 +688,6 @@ G4double G4DNABornIonisationModel1::RandomizeEjectedElectronEnergy(G4ParticleDef
|
||||
return 0;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
// The following section is not used anymore but is kept for memory
|
||||
// GetAngularDistribution()->SampleDirectionForShell is used instead
|
||||
|
||||
/*
|
||||
void G4DNABornIonisationModel1::RandomizeEjectedElectronDirection(G4ParticleDefinition* particleDefinition,
|
||||
G4double k,
|
||||
G4double secKinetic,
|
||||
G4double & cosTheta,
|
||||
G4double & phi )
|
||||
{
|
||||
if (particleDefinition == G4Electron::ElectronDefinition())
|
||||
{
|
||||
phi = twopi * G4UniformRand();
|
||||
if (secKinetic < 50.*eV) cosTheta = (2.*G4UniformRand())-1.;
|
||||
else if (secKinetic <= 200.*eV)
|
||||
{
|
||||
if (G4UniformRand() <= 0.1) cosTheta = (2.*G4UniformRand())-1.;
|
||||
else cosTheta = G4UniformRand()*(std::sqrt(2.)/2);
|
||||
}
|
||||
else
|
||||
{
|
||||
G4double sin2O = (1.-secKinetic/k) / (1.+secKinetic/(2.*electron_mass_c2));
|
||||
cosTheta = std::sqrt(1.-sin2O);
|
||||
}
|
||||
}
|
||||
|
||||
else if (particleDefinition == G4Proton::ProtonDefinition())
|
||||
{
|
||||
G4double maxSecKinetic = 4.* (electron_mass_c2 / proton_mass_c2) * k;
|
||||
phi = twopi * G4UniformRand();
|
||||
|
||||
// cosTheta = std::sqrt(secKinetic / maxSecKinetic);
|
||||
|
||||
// Restriction below 100 eV from Emfietzoglou (2000)
|
||||
|
||||
if (secKinetic>100*eV) cosTheta = std::sqrt(secKinetic / maxSecKinetic);
|
||||
else cosTheta = (2.*G4UniformRand())-1.;
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
G4double G4DNABornIonisationModel1::DifferentialCrossSection(G4ParticleDefinition * particleDefinition,
|
||||
G4double k,
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "G4LossTableManager.hh"
|
||||
#include "G4DNAChemistryManager.hh"
|
||||
#include "G4DNAMolecularMaterial.hh"
|
||||
#include "G4EmParameters.hh"
|
||||
#include "G4DNABornAngle.hh"
|
||||
#include "G4DeltaAngle.hh"
|
||||
#include "G4Exp.hh"
|
||||
@@ -91,13 +92,7 @@ G4VEmModel(nam)
|
||||
|
||||
G4DNABornIonisationModel2::~G4DNABornIonisationModel2()
|
||||
{
|
||||
// Cross section
|
||||
|
||||
|
||||
delete fTableData;
|
||||
|
||||
// Final state
|
||||
|
||||
delete fTableData;
|
||||
fVecm.clear();
|
||||
}
|
||||
|
||||
@@ -248,13 +243,14 @@ void G4DNABornIonisationModel2::Initialise(const G4ParticleDefinition* particle,
|
||||
fpMolWaterDensity = G4DNAMolecularMaterial::Instance()->
|
||||
GetNumMolPerVolTableFor(G4Material::GetMaterial("G4_WATER"));
|
||||
|
||||
// AD
|
||||
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
|
||||
if (isInitialised)
|
||||
{ return;}
|
||||
fParticleChangeForGamma = GetParticleChangeForGamma();
|
||||
statCode = G4EmParameters::Instance()->DNAStationary();
|
||||
|
||||
if (!statCode)
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
|
||||
isInitialised = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,79 +44,58 @@ G4DNAEventScheduler::G4DNAEventScheduler()
|
||||
, fpUpdateSystem(new G4DNAUpdateSystemModel())
|
||||
{}
|
||||
|
||||
void G4DNAEventScheduler::ClearAndReChargeCounter()
|
||||
{
|
||||
fCounterMap.clear();
|
||||
if(fTimeToRecord.empty())
|
||||
{
|
||||
G4String WarMessage = "fTimeToRecord is empty ";
|
||||
G4Exception("G4DNAEventScheduler::ClearAndReChargeCounter()",
|
||||
"TimeToRecord is empty", JustWarning, WarMessage);
|
||||
}
|
||||
fLastRecoredTime = fTimeToRecord.begin();
|
||||
|
||||
if(G4VMoleculeCounter::Instance()->InUse()) // copy from MoleculeCounter
|
||||
{
|
||||
G4MoleculeCounter::RecordedMolecules species;
|
||||
species = G4MoleculeCounter::Instance()->GetRecordedMolecules();
|
||||
if(species.get() == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(species->empty())
|
||||
{
|
||||
G4MoleculeCounter::Instance()->ResetCounter();
|
||||
return;
|
||||
}
|
||||
for(auto time_mol : fTimeToRecord)
|
||||
{
|
||||
if(time_mol > fStartTime)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for(auto molecule : *species)
|
||||
{
|
||||
G4int n_mol = G4MoleculeCounter::Instance()->GetNMoleculesAtTime(
|
||||
molecule, time_mol);
|
||||
|
||||
if(n_mol < 0)
|
||||
{
|
||||
G4cerr << "G4DNAEventScheduler::ClearAndReChargeCounter() ::N "
|
||||
"molecules not valid < 0 "
|
||||
<< G4endl;
|
||||
G4Exception("", "N<0", FatalException, "");
|
||||
}
|
||||
fCounterMap[time_mol][molecule] = n_mol;
|
||||
}
|
||||
fLastRecoredTime++;
|
||||
}
|
||||
G4MoleculeCounter::Instance()->ResetCounter(); // reset
|
||||
G4MoleculeCounter::Instance()->Use(false); // no more used
|
||||
}
|
||||
else
|
||||
{
|
||||
G4ExceptionDescription exceptionDescription;
|
||||
exceptionDescription << "G4VMoleculeCounter is not used";
|
||||
G4Exception("G4DNAEventScheduler::ClearAndReChargeCounter()",
|
||||
"G4DNAEventScheduler010", JustWarning, exceptionDescription);
|
||||
}
|
||||
}
|
||||
|
||||
[[maybe_unused]] void G4DNAEventScheduler::AddTimeToRecord(const G4double& time)
|
||||
{
|
||||
if(fTimeToRecord.find(time) == fTimeToRecord.end())
|
||||
{
|
||||
fTimeToRecord.insert(time);
|
||||
}
|
||||
fLastRecoredTime = fTimeToRecord.begin();
|
||||
}
|
||||
|
||||
G4DNAEventScheduler::~G4DNAEventScheduler() = default;
|
||||
|
||||
void G4DNAEventScheduler::Voxelizing()
|
||||
void G4DNAEventScheduler::Voxelizing(const G4DNABoundingBox& boundingBox)
|
||||
{
|
||||
auto pMainList = G4ITTrackHolder::Instance()->GetMainList();
|
||||
std::map<G4VDNAMesh::Index, MapList> TrackKeyMap;
|
||||
if(fpMesh == nullptr){
|
||||
fpMesh = std::make_unique<G4DNAMesh>(boundingBox, fPixel);
|
||||
}else
|
||||
{
|
||||
auto newMesh = new G4DNAMesh(fpMesh->GetBoundingBox(), fPixel);
|
||||
|
||||
auto begin = fpMesh->begin();//old mesh, should be homogeneous
|
||||
auto end = fpMesh->end();
|
||||
for(; begin != end; begin++)
|
||||
{
|
||||
auto numberOfBoxes = fPixel*fPixel*fPixel;
|
||||
const auto& mapData = std::get<2>(*begin);
|
||||
for(auto it : mapData)
|
||||
{
|
||||
if(it.second == 0) continue;
|
||||
|
||||
G4int base_mol = std::floor((G4double)it.second / numberOfBoxes);
|
||||
G4int remainder = (G4int)it.second % numberOfBoxes;
|
||||
for(G4int i = 0; i < remainder; i++)
|
||||
{
|
||||
auto oldIndex = std::get<0>(*begin);
|
||||
auto idx = newMesh->GetRandomIndex(oldIndex, fpMesh->GetResolution());
|
||||
TrackKeyMap[idx][it.first] += base_mol + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
fpMesh.reset(newMesh);
|
||||
}
|
||||
|
||||
if(!CheckingReactionRadius(fpMesh->GetResolution()))
|
||||
{
|
||||
G4String WarMessage = "resolution is not good : " +
|
||||
std::to_string(fpMesh->GetResolution() / nm);
|
||||
G4Exception("G4DNAEventScheduler::InitializeInMesh()", "WrongResolution",
|
||||
JustWarning, WarMessage);
|
||||
}
|
||||
|
||||
auto pMainList = G4ITTrackHolder::Instance()->GetMainList();
|
||||
for(auto track : *pMainList)
|
||||
{
|
||||
auto molType = GetMolecule(track)->GetMolecularConfiguration();
|
||||
@@ -146,7 +125,9 @@ void G4DNAEventScheduler::Voxelizing()
|
||||
{
|
||||
TrackKeyMap[key][molType] = 1;
|
||||
}
|
||||
track->SetTrackStatus(fStopAndKill);//kill the track
|
||||
}
|
||||
G4ITReactionSet::Instance()->CleanAllReaction();
|
||||
|
||||
for(auto& it : TrackKeyMap)
|
||||
{
|
||||
@@ -212,9 +193,12 @@ void G4DNAEventScheduler::Reset()
|
||||
fRunning = true;
|
||||
fReactionNumber = 0;
|
||||
fJumpingNumber = 0;
|
||||
|
||||
fpEventSet->RemoveEventSet();
|
||||
fpMesh->Reset();
|
||||
if(fpMesh != nullptr) {
|
||||
fpMesh->Reset();
|
||||
fpMesh.reset();
|
||||
//reset for each event
|
||||
}
|
||||
fpGillespieReaction->ResetEquilibrium();
|
||||
}
|
||||
|
||||
@@ -224,16 +208,6 @@ void G4DNAEventScheduler::Initialize(const G4DNABoundingBox& boundingBox,
|
||||
if(!fInitialized)
|
||||
{
|
||||
fPixel = pixel;
|
||||
fpMesh = std::make_unique<G4DNAMesh>(boundingBox, pixel);
|
||||
|
||||
if(!CheckingReactionRadius(fpMesh->GetResolution()))
|
||||
{
|
||||
G4String WarMessage = "resolution is not good : " +
|
||||
std::to_string(fpMesh->GetResolution() / nm);
|
||||
G4Exception("G4DNAEventScheduler::InitializeInMesh()", "WrongResolution",
|
||||
JustWarning, WarMessage);
|
||||
}
|
||||
|
||||
// Scavenger();
|
||||
|
||||
auto pScavengerMaterial = dynamic_cast<G4DNAScavengerMaterial*>(
|
||||
@@ -250,14 +224,17 @@ void G4DNAEventScheduler::Initialize(const G4DNABoundingBox& boundingBox,
|
||||
}
|
||||
}
|
||||
|
||||
Voxelizing();
|
||||
Voxelizing(boundingBox);
|
||||
fEndTime = std::min(G4ITTrackHolder::Instance()->GetNextTime(), G4Scheduler::Instance()->GetEndTime()-1*ps);
|
||||
|
||||
//G4cout<<"fEndTime" <<fEndTime<<" G4ITTrackHolder::Instance()->GetNextTime() : "<<G4ITTrackHolder::Instance()->GetNextTime()<<G4endl;
|
||||
|
||||
fpGillespieReaction->SetVoxelMesh(*fpMesh);
|
||||
fpGillespieReaction->SetEventSet(fpEventSet.get());
|
||||
fpGillespieReaction->SetTimeStep(0);// reset fTimeStep = 0 in fpGillespieReaction
|
||||
fpGillespieReaction->Initialize();
|
||||
fpGillespieReaction->CreateEvents();
|
||||
fpUpdateSystem->SetMesh(fpMesh.get());
|
||||
ClearAndReChargeCounter();
|
||||
fInitialized = true;
|
||||
}
|
||||
|
||||
@@ -305,6 +282,8 @@ void G4DNAEventScheduler::ResetInMesh()
|
||||
|
||||
G4double G4DNAEventScheduler::GetStartTime() const { return fStartTime; }
|
||||
|
||||
G4double G4DNAEventScheduler::GetGlobalTime() const { return fGlobalTime; }
|
||||
|
||||
G4double G4DNAEventScheduler::GetEndTime() const { return fEndTime; }
|
||||
|
||||
[[maybe_unused]] G4double G4DNAEventScheduler::GetTimeStep() const
|
||||
@@ -338,6 +317,7 @@ void G4DNAEventScheduler::Run()
|
||||
{
|
||||
RunInMesh();
|
||||
}
|
||||
fInitialized = false;
|
||||
if(fVerbose > 2)
|
||||
{
|
||||
if(!fRunning)
|
||||
@@ -361,7 +341,6 @@ void G4DNAEventScheduler::Run()
|
||||
}
|
||||
G4cout << " Computing Time : " << localtimer << G4endl;
|
||||
}
|
||||
Reset();
|
||||
}
|
||||
|
||||
void G4DNAEventScheduler::RunInMesh()
|
||||
@@ -377,7 +356,7 @@ void G4DNAEventScheduler::RunInMesh()
|
||||
<< " the Mesh has " << fPixel << " x " << fPixel << " x " << fPixel
|
||||
<< " voxels with Resolution " << G4BestUnit(resolution, "Length")
|
||||
<< " during next "
|
||||
<< G4BestUnit(resolution * resolution * C / (6 * D), "Time")
|
||||
<< G4BestUnit(fGlobalTime + resolution * resolution * C / (6 * D), "Time")
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
@@ -501,6 +480,8 @@ void G4DNAEventScheduler::Stepping() // this event loop
|
||||
// get selected time step
|
||||
fTimeStep = (*selected)->GetTime();
|
||||
|
||||
if(fTimeStep + fStartTime >fEndTime){ return;}
|
||||
|
||||
// selected data
|
||||
auto pJumping = (*selected)->GetJumpingData();
|
||||
auto pReaction = (*selected)->GetReactionData();
|
||||
@@ -564,9 +545,15 @@ void G4DNAEventScheduler::SetEndTime(const G4double& endTime)
|
||||
|
||||
void G4DNAEventScheduler::RecordTime()
|
||||
{
|
||||
if(fLastRecoredTime == fTimeToRecord.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto recordTime = *fLastRecoredTime;
|
||||
if(fGlobalTime >= recordTime && fCounterMap[recordTime].empty())
|
||||
{
|
||||
if(fpMesh == nullptr) return;
|
||||
//G4cout<<"recordTime for meso: "<<recordTime<<" fGlobalTime : "<<fGlobalTime<<G4endl;
|
||||
auto begin = fpMesh->begin();
|
||||
auto end = fpMesh->end();
|
||||
for(; begin != end; begin++)
|
||||
@@ -671,4 +658,63 @@ void G4DNAEventScheduler::LastRegisterForCounter()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void G4DNAEventScheduler::ParticleBasedCounter() {
|
||||
if(fLastRecoredTime == fTimeToRecord.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto recordTime = *fLastRecoredTime;
|
||||
if (recordTime < G4Scheduler::Instance()->GetGlobalTime()) {
|
||||
|
||||
//check meso if exist
|
||||
|
||||
if(fpMesh != nullptr){
|
||||
//G4cout<<"there is a mesh"<<G4endl;
|
||||
auto begin = fpMesh->begin();
|
||||
auto end = fpMesh->end();
|
||||
for(; begin != end; begin++)
|
||||
{
|
||||
const auto& mapData = std::get<2>(*begin);
|
||||
if(mapData.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for(const auto& it : mapData)
|
||||
{
|
||||
fCounterMap[recordTime][it.first] += it.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//then particle based
|
||||
auto pMainList = G4ITTrackHolder::Instance()->GetMainList();
|
||||
for (auto track: *pMainList) {
|
||||
auto molType = GetMolecule(track)->GetMolecularConfiguration();
|
||||
|
||||
auto pScavengerMaterial =
|
||||
dynamic_cast<G4DNAScavengerMaterial *>(G4Scheduler::Instance()->GetScavengerMaterial());
|
||||
if (pScavengerMaterial != nullptr
|
||||
&& pScavengerMaterial->find(molType)) // avoid voxelize the scavenger
|
||||
{
|
||||
continue;
|
||||
}
|
||||
fCounterMap[recordTime][molType]++;
|
||||
}
|
||||
fLastRecoredTime++;
|
||||
//PrintRecordTime();
|
||||
}
|
||||
}
|
||||
|
||||
void G4DNAEventScheduler::ResetCounter()
|
||||
{
|
||||
fCounterMap.clear();
|
||||
if(fTimeToRecord.empty())
|
||||
{
|
||||
G4String WarMessage = "fTimeToRecord is empty ";
|
||||
G4Exception("G4DNAEventScheduler::ClearAndReChargeCounter()",
|
||||
"TimeToRecord is empty", JustWarning, WarMessage);
|
||||
}
|
||||
fLastRecoredTime = fTimeToRecord.begin();
|
||||
}
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "G4ITTrackHolder.hh"
|
||||
#include "G4ITReaction.hh"
|
||||
#include "G4Scheduler.hh"
|
||||
#include "G4MoleculeCounterManager.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -399,7 +400,10 @@ std::unique_ptr<G4ITReactionChange> G4DNAIRT::MakeReaction(const G4Track& trackA
|
||||
const auto pMoleculeA = GetMolecule(trackA)->GetMolecularConfiguration();
|
||||
const auto pMoleculeB = GetMolecule(trackB)->GetMolecularConfiguration();
|
||||
const auto pReactionData = fMolReactionTable->GetReactionData(pMoleculeA, pMoleculeB);
|
||||
|
||||
// Notify molecule (reaction) counter
|
||||
if (G4MoleculeCounterManager::Instance()->GetIsActive()) {
|
||||
G4MoleculeCounterManager::Instance()->RecordReaction(pReactionData, trackA.GetGlobalTime());
|
||||
}
|
||||
G4double globalTime = G4Scheduler::Instance()->GetGlobalTime();
|
||||
G4double effectiveReactionRadius = pReactionData->GetEffectiveReactionRadius();
|
||||
|
||||
|
||||
+164
-145
@@ -45,10 +45,11 @@ using namespace std;
|
||||
using namespace CLHEP;
|
||||
|
||||
G4DNAIndependentReactionTimeStepper::Utils::Utils(const G4Track& trackA, const G4Track& trackB)
|
||||
: fTrackA(trackA), fTrackB(trackB)
|
||||
: fpTrackA(const_cast<G4Track*>(&trackA)), fpTrackB(const_cast<G4Track*>(&trackB))
|
||||
{
|
||||
fpMoleculeA = GetMolecule(trackA);
|
||||
fpMoleculeB = GetMolecule(trackA);
|
||||
fpMoleculeB = GetMolecule(trackB);
|
||||
fUserMinTimeStep = 1 * CLHEP::ps;
|
||||
}
|
||||
|
||||
G4DNAIndependentReactionTimeStepper::G4DNAIndependentReactionTimeStepper()
|
||||
@@ -58,30 +59,31 @@ G4DNAIndependentReactionTimeStepper::G4DNAIndependentReactionTimeStepper()
|
||||
|
||||
void G4DNAIndependentReactionTimeStepper::Prepare()
|
||||
{
|
||||
G4VITTimeStepComputer::Prepare();
|
||||
fSampledPositions.clear();
|
||||
BuildChemicalMoleculeFinder()
|
||||
//fVerbose = G4Scheduler::Instance()->GetVerbose();
|
||||
if (G4Scheduler::Instance()->IsInteractionStep()) {
|
||||
fReactionSet->CleanAllReaction();
|
||||
fIsInitialized = false;
|
||||
fSampledPositions.clear();
|
||||
fSecondaries.clear();
|
||||
InitializeForNewTrack();
|
||||
}
|
||||
}
|
||||
|
||||
void G4DNAIndependentReactionTimeStepper::InitializeForNewTrack()
|
||||
{
|
||||
if (fReactants != nullptr) {
|
||||
fReactants.reset();
|
||||
}
|
||||
fSampledMinTimeStep = DBL_MAX;
|
||||
fHasAlreadyReachedNullTime = false;
|
||||
fCheckedTracks.clear();
|
||||
BuildChemicalMoleculeFinder()
|
||||
}
|
||||
|
||||
G4double G4DNAIndependentReactionTimeStepper::CalculateStep(const G4Track& trackA,
|
||||
const G4double& userMinTimeStep)
|
||||
const G4double& /*userMinTimeStep*/)
|
||||
{
|
||||
auto pMoleculeA = GetMolecule(trackA);
|
||||
InitializeForNewTrack();
|
||||
fUserMinTimeStep = userMinTimeStep;
|
||||
fSampledMinTimeStep = DBL_MAX;
|
||||
fCheckedTracks.insert(trackA.GetTrackID());
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if (fVerbose != 0) {
|
||||
if (fVerbose > 1) {
|
||||
G4cout << "________________________________________________________________"
|
||||
"_______"
|
||||
<< G4endl;
|
||||
@@ -96,7 +98,7 @@ G4double G4DNAIndependentReactionTimeStepper::CalculateStep(const G4Track& track
|
||||
const auto pReactantList = fMolecularReactionTable->CanReactWith(pMolConfA);
|
||||
|
||||
if (pReactantList == nullptr) {
|
||||
if(fVerbose > 1) {
|
||||
if (fVerbose > 1) {
|
||||
G4ExceptionDescription msg;
|
||||
msg << "G4DNAIndependentReactionTimeStepper::CalculateStep will return infinity "
|
||||
"for the reaction because the molecule "
|
||||
@@ -111,7 +113,7 @@ G4double G4DNAIndependentReactionTimeStepper::CalculateStep(const G4Track& track
|
||||
auto nbReactives = (G4int)pReactantList->size();
|
||||
|
||||
if (nbReactives == 0) {
|
||||
if(fVerbose != 0){
|
||||
if (fVerbose > 1) {
|
||||
G4ExceptionDescription msg;
|
||||
msg << "G4DNAIndependentReactionTimeStepper::CalculateStep will "
|
||||
"return infinity "
|
||||
@@ -125,13 +127,10 @@ G4double G4DNAIndependentReactionTimeStepper::CalculateStep(const G4Track& track
|
||||
}
|
||||
return DBL_MAX;
|
||||
}
|
||||
fReactants = std::make_shared<vector<G4Track*>>();
|
||||
fReactionModel->Initialise(pMolConfA, trackA);
|
||||
for (G4int i = 0; i < nbReactives; ++i) {
|
||||
auto pMoleculeB = (*pReactantList)[i];
|
||||
G4int key = pMoleculeB->GetMoleculeID();
|
||||
|
||||
// fRCutOff = G4IRTUtils::GetRCutOff(1 * ps);
|
||||
fRCutOff = G4IRTUtils::GetRCutOff();
|
||||
//______________________________________________________________
|
||||
// Retrieve reaction range
|
||||
@@ -157,115 +156,107 @@ G4double G4DNAIndependentReactionTimeStepper::CalculateStep(const G4Track& track
|
||||
"::CalculateStep()",
|
||||
"G4DNAIndependentReactionTimeStepper007", FatalException, exceptionDescription);
|
||||
}
|
||||
if (fCheckedTracks.find(pTrackB->GetTrackID()) != fCheckedTracks.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Utils utils(trackA, *pTrackB);
|
||||
auto pMolB = GetMolecule(pTrackB);
|
||||
auto pMolConfB = pMolB->GetMolecularConfiguration();
|
||||
G4double distance = (trackA.GetPosition() - pTrackB->GetPosition()).mag();
|
||||
if (distance * distance < Reff * Reff) {
|
||||
auto reactionData = fMolecularReactionTable->GetReactionData(pMolConfA, pMolConfB);
|
||||
if (G4Scheduler::Instance()->GetGlobalTime() == G4Scheduler::Instance()->GetStartTime()) {
|
||||
if (reactionData->GetProbability() > G4UniformRand()) {
|
||||
fSampledMinTimeStep = 0.;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (fCheckedTracks.find(pTrackB->GetTrackID()) != fCheckedTracks.end()) {
|
||||
G4double tempMinET = GetTimeToEncounter(trackA, *pTrackB);
|
||||
if (tempMinET < 0 || tempMinET > G4Scheduler::Instance()->GetEndTime()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Utils utils(trackA, *pTrackB);
|
||||
|
||||
auto pMolB = GetMolecule(pTrackB);
|
||||
auto pMolConfB = pMolB->GetMolecularConfiguration();
|
||||
G4double distance = (trackA.GetPosition() - pTrackB->GetPosition()).mag();
|
||||
if (distance * distance < Reff * Reff) {
|
||||
auto reactionData = fMolecularReactionTable->GetReactionData(pMolConfA, pMolConfB);
|
||||
if (G4Scheduler::Instance()->GetGlobalTime() == G4Scheduler::Instance()->GetStartTime()) {
|
||||
if (reactionData->GetProbability() > G4UniformRand()) {
|
||||
if (!fHasAlreadyReachedNullTime) {
|
||||
fReactants->clear();
|
||||
fHasAlreadyReachedNullTime = true;
|
||||
}
|
||||
fSampledMinTimeStep = 0.;
|
||||
CheckAndRecordResults(utils);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
G4double tempMinET = GetTimeToEncounter(trackA, *pTrackB);
|
||||
if (tempMinET < 0 || tempMinET > G4Scheduler::Instance()->GetEndTime()) {
|
||||
continue;
|
||||
}
|
||||
if (tempMinET >= fSampledMinTimeStep) {
|
||||
continue;
|
||||
}
|
||||
fSampledMinTimeStep = tempMinET;
|
||||
fReactants->clear();
|
||||
CheckAndRecordResults(utils);
|
||||
fSampledMinTimeStep = tempMinET;
|
||||
if (tempMinET < fUserMinTimeStep) {
|
||||
fSampledMinTimeStep = fUserMinTimeStep;
|
||||
}
|
||||
}
|
||||
CheckAndRecordResults(fSampledMinTimeStep, utils);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if (fVerbose != 0) {
|
||||
G4cout << "G4DNAIndependentReactionTimeStepper::CalculateStep will finally "
|
||||
"return :"
|
||||
<< G4BestUnit(fSampledMinTimeStep, "Time") << G4endl;
|
||||
|
||||
if (fVerbose > 1) {
|
||||
G4cout << "Selected reactants for trackA: " << pMoleculeA->GetName() << " ("
|
||||
<< trackA.GetTrackID() << ") are: ";
|
||||
|
||||
vector<G4Track*>::iterator it;
|
||||
for (it = fReactants->begin(); it != fReactants->end(); it++) {
|
||||
G4Track* trackB = *it;
|
||||
G4cout << GetMolecule(trackB)->GetName() << " (" << trackB->GetTrackID() << ") \t ";
|
||||
}
|
||||
G4cout << G4endl;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return fSampledMinTimeStep;
|
||||
}
|
||||
|
||||
void G4DNAIndependentReactionTimeStepper::CheckAndRecordResults(const Utils& utils)
|
||||
void G4DNAIndependentReactionTimeStepper::CheckAndRecordResults(G4double reactionTime,
|
||||
const Utils& utils)
|
||||
{
|
||||
if (utils.fTrackB.GetTrackStatus() != fAlive) {
|
||||
if (utils.fpTrackB->GetTrackStatus() != fAlive) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (&utils.fTrackB == &utils.fTrackA) {
|
||||
if (&utils.fpTrackB == &utils.fpTrackA) {
|
||||
G4ExceptionDescription msg;
|
||||
msg << "A track is reacting with itself"
|
||||
" (which is impossible) ie fpTrackA == trackB"
|
||||
<< G4endl;
|
||||
" (which is impossible) ie fpTrackA == trackB"
|
||||
<< G4endl;
|
||||
msg << "Molecule A is of type : " << utils.fpMoleculeA->GetName()
|
||||
<< " with trackID : " << utils.fTrackA.GetTrackID()
|
||||
<< " and B : " << utils.fpMoleculeB->GetName()
|
||||
<< " with trackID : " << utils.fTrackB.GetTrackID() << G4endl;
|
||||
<< " with trackID : " << utils.fpTrackA->GetTrackID()
|
||||
<< " and B : " << utils.fpMoleculeB->GetName()
|
||||
<< " with trackID : " << utils.fpTrackB->GetTrackID() << G4endl;
|
||||
G4Exception("G4DNAIndependentReactionTimeStepper::RetrieveResults",
|
||||
"G4DNAIndependentReactionTimeStepper003", FatalErrorInArgument,
|
||||
msg);
|
||||
"G4DNAIndependentReactionTimeStepper003", FatalErrorInArgument, msg);
|
||||
}
|
||||
|
||||
if (fabs(utils.fTrackB.GetGlobalTime() - utils.fTrackA.GetGlobalTime())
|
||||
> utils.fTrackA.GetGlobalTime() * (1. - 1. / 100))
|
||||
if (fabs(utils.fpTrackB->GetGlobalTime() - utils.fpTrackA->GetGlobalTime())
|
||||
> utils.fpTrackA->GetGlobalTime() * (1. - 1. / 100))
|
||||
{
|
||||
// DEBUG
|
||||
G4ExceptionDescription msg;
|
||||
msg << "The interacting tracks are not synchronized in time" << G4endl;
|
||||
msg << "trackB->GetGlobalTime() != fpTrackA.GetGlobalTime()" << G4endl;
|
||||
|
||||
msg << "fpTrackA : trackID : " << utils.fTrackA.GetTrackID()
|
||||
<< "\t Name :" << utils.fpMoleculeA->GetName()
|
||||
<< "\t fpTrackA->GetGlobalTime() = "
|
||||
<< G4BestUnit(utils.fTrackA.GetGlobalTime(), "Time") << G4endl;
|
||||
msg << "fpTrackA : trackID : " << utils.fpTrackA->GetTrackID()
|
||||
<< "\t Name :" << utils.fpMoleculeA->GetName()
|
||||
<< "\t fpTrackA->GetGlobalTime() = " << G4BestUnit(utils.fpTrackA->GetGlobalTime(), "Time")
|
||||
<< G4endl;
|
||||
|
||||
msg << "trackB : trackID : " << utils.fTrackB.GetTrackID()
|
||||
<< "\t Name :" << utils.fpMoleculeB->GetName()
|
||||
<< "\t trackB->GetGlobalTime() = "
|
||||
<< G4BestUnit(utils.fTrackB.GetGlobalTime(), "Time") << G4endl;
|
||||
msg << "trackB : trackID : " << utils.fpTrackB->GetTrackID()
|
||||
<< "\t Name :" << utils.fpMoleculeB->GetName()
|
||||
<< "\t trackB->GetGlobalTime() = " << G4BestUnit(utils.fpTrackB->GetGlobalTime(), "Time")
|
||||
<< G4endl;
|
||||
|
||||
G4Exception("G4DNAIndependentReactionTimeStepper::RetrieveResults",
|
||||
"G4DNAIndependentReactionTimeStepper004", FatalErrorInArgument,
|
||||
msg);
|
||||
"G4DNAIndependentReactionTimeStepper004", FatalErrorInArgument, msg);
|
||||
}
|
||||
fReactants->push_back(const_cast<G4Track*>(&utils.fTrackB));
|
||||
if (reactionTime < 0) {
|
||||
// DEBUG
|
||||
G4ExceptionDescription msg;
|
||||
msg << "The interacting tracks are not in good time" << G4endl;
|
||||
|
||||
msg << "fpTrackA : trackID : " << utils.fpTrackA->GetTrackID()
|
||||
<< "\t Name :" << utils.fpMoleculeA->GetName()
|
||||
<< "\t fpTrackA->GetGlobalTime() = " << G4BestUnit(utils.fpTrackA->GetGlobalTime(), "Time")
|
||||
<< G4endl;
|
||||
|
||||
msg << "trackB : trackID : " << utils.fpTrackB->GetTrackID()
|
||||
<< "\t Name :" << utils.fpMoleculeB->GetName()
|
||||
<< "\t trackB->GetGlobalTime() = " << G4BestUnit(utils.fpTrackB->GetGlobalTime(), "Time")
|
||||
<< G4endl;
|
||||
|
||||
G4Exception("G4DNAIndependentReactionTimeStepper::CheckAndRecordResults",
|
||||
"G4DNAIndependentReactionTimeStepper1", FatalErrorInArgument, msg);
|
||||
}
|
||||
|
||||
G4double globalTime = G4Scheduler::Instance()->GetGlobalTime();
|
||||
|
||||
fReactionSet->AddReaction(reactionTime + globalTime, utils.fpTrackA, utils.fpTrackB);
|
||||
fSampledPositions[utils.fpTrackA->GetTrackID()] = utils.fpTrackA->GetPosition();
|
||||
fSampledPositions[utils.fpTrackB->GetTrackID()] = utils.fpTrackB->GetPosition();
|
||||
}
|
||||
|
||||
std::unique_ptr<G4ITReactionChange> G4DNAIndependentReactionTimeStepper::FindReaction(
|
||||
G4ITReactionSet* pReactionSet, const G4double& currentStepTime,
|
||||
const G4double& /*previousStepTime*/, const G4bool& /*reachedUserStepTimeLimit*/)
|
||||
G4ITReactionSet* pReactionSet, G4double& currentStepTime, const G4double globalTime)
|
||||
{
|
||||
if (pReactionSet == nullptr) {
|
||||
return nullptr;
|
||||
@@ -278,16 +269,13 @@ std::unique_ptr<G4ITReactionChange> G4DNAIndependentReactionTimeStepper::FindRea
|
||||
for (auto reaction_i = reactionPerTime.begin(); reaction_i != reactionPerTime.end();
|
||||
reaction_i = reactionPerTime.begin())
|
||||
{
|
||||
if ((*reaction_i)->GetTime() > currentStepTime) {
|
||||
fReactionSet->CleanAllReaction();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
G4Track* pTrackA = (*reaction_i)->GetReactants().first;
|
||||
currentStepTime = DBL_MAX;
|
||||
if (pTrackA->GetTrackStatus() == fStopAndKill) {
|
||||
continue;
|
||||
}
|
||||
G4Track* pTrackB = (*reaction_i)->GetReactant(pTrackA);
|
||||
currentStepTime = DBL_MAX;
|
||||
if (pTrackB->GetTrackStatus() == fStopAndKill) {
|
||||
continue;
|
||||
}
|
||||
@@ -295,24 +283,27 @@ std::unique_ptr<G4ITReactionChange> G4DNAIndependentReactionTimeStepper::FindRea
|
||||
if (pTrackB == pTrackA) {
|
||||
G4ExceptionDescription msg;
|
||||
msg << "The IT reaction process sent back a reaction "
|
||||
"between trackA and trackB. ";
|
||||
"between trackA and trackB. ";
|
||||
msg << "The problem is trackA == trackB";
|
||||
G4Exception("G4DNAIndependentReactionTimeStepper::FindReaction",
|
||||
"G4DNAIndependentReactionTimeStepper02", FatalErrorInArgument,
|
||||
msg);
|
||||
"G4DNAIndependentReactionTimeStepper02", FatalErrorInArgument, msg);
|
||||
}
|
||||
G4double reactionTime = (*reaction_i)->GetTime();
|
||||
currentStepTime = reactionTime - globalTime;
|
||||
if(fVerbose > 1)
|
||||
G4cout << " reaction Time : " << reactionTime << " currentStepTime : " << currentStepTime
|
||||
<< " globalTime : " << globalTime << " " << pTrackA->GetTrackID() << " + "
|
||||
<< pTrackB->GetTrackID() << G4endl;
|
||||
|
||||
pReactionSet->SelectThisReaction(*reaction_i);
|
||||
if (fpReactionProcess != nullptr
|
||||
&& fpReactionProcess->TestReactibility(*pTrackA, *pTrackB, currentStepTime, false))
|
||||
{
|
||||
if (fpReactionProcess != nullptr) {
|
||||
if ((fSampledPositions.find(pTrackA->GetTrackID()) == fSampledPositions.end()
|
||||
&& (fSampledPositions.find(pTrackB->GetTrackID()) == fSampledPositions.end())))
|
||||
{
|
||||
G4ExceptionDescription msg;
|
||||
msg << "The positions of trackA and trackB have no counted ";
|
||||
G4Exception("G4DNAIndependentReactionTimeStepper::FindReaction",
|
||||
"G4DNAIndependentReactionTimeStepper0001", FatalErrorInArgument,
|
||||
msg);
|
||||
"G4DNAIndependentReactionTimeStepper0001", FatalErrorInArgument, msg);
|
||||
}
|
||||
|
||||
pTrackA->SetPosition(fSampledPositions[pTrackA->GetTrackID()]);
|
||||
@@ -321,6 +312,13 @@ std::unique_ptr<G4ITReactionChange> G4DNAIndependentReactionTimeStepper::FindRea
|
||||
if (pReactionChange == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
G4int nbSecondaries = pReactionChange->GetNumberOfSecondaries();
|
||||
if (nbSecondaries > 0) {
|
||||
const std::vector<G4Track*>* productsVector = pReactionChange->GetfSecondary();
|
||||
for (const auto& it : *productsVector) {
|
||||
fSecondaries.push_back(it);
|
||||
}
|
||||
}
|
||||
return pReactionChange;
|
||||
}
|
||||
}
|
||||
@@ -354,19 +352,44 @@ void G4DNAIndependentReactionTimeStepper::SetReactionProcess(G4VITReactionProces
|
||||
{
|
||||
fpReactionProcess = pReactionProcess;
|
||||
}
|
||||
G4double G4DNAIndependentReactionTimeStepper::CalculateMinTimeStep(G4double /*currentGlobalTime*/,
|
||||
G4double definedMinTimeStep)
|
||||
G4double G4DNAIndependentReactionTimeStepper::CalculateMinTimeStep(G4double currentGlobalTime,
|
||||
G4double /*definedMinTimeStep*/)
|
||||
{
|
||||
G4double fTSTimeStep = DBL_MAX;
|
||||
fCheckedTracks.clear();
|
||||
// fUserMinTimeStep = definedMinTimeStep;
|
||||
if (!fIsInitialized) {
|
||||
InitializeReactions(currentGlobalTime);
|
||||
}
|
||||
|
||||
G4int nbPreviousSecondaries = (G4int)fSecondaries.size();
|
||||
if (nbPreviousSecondaries > 0) {
|
||||
InitializeForNewTrack();
|
||||
for (const auto& it : fSecondaries) {
|
||||
CalculateStep(*it, fUserMinTimeStep);
|
||||
}
|
||||
fSecondaries.clear();
|
||||
}
|
||||
fTSTimeStep = GetNextReactionTime() - currentGlobalTime;
|
||||
if (fTSTimeStep < 0) {
|
||||
G4ExceptionDescription msg;
|
||||
msg << "fTSTimeStep < 0" << ": fTSTimeStep : " << fTSTimeStep
|
||||
<< " GetNextReactionTime() : " << GetNextReactionTime()
|
||||
<< " currentGlobalTime : " << currentGlobalTime << G4endl;
|
||||
G4Exception("G4DNAIndependentReactionTimeStepper::CalculateMinTimeStep",
|
||||
"G4DNAIndependentReactionTimeStepper002", FatalErrorInArgument, msg);
|
||||
}
|
||||
return fTSTimeStep;
|
||||
}
|
||||
|
||||
void G4DNAIndependentReactionTimeStepper::InitializeReactions(G4double /*currentGlobalTime*/)
|
||||
{
|
||||
fCheckedTracks.clear();
|
||||
for (auto pTrack : *fpTrackContainer->GetMainList()) {
|
||||
if (pTrack == nullptr) {
|
||||
G4ExceptionDescription msg;
|
||||
msg << "No track found.";
|
||||
G4Exception("G4DNAIndependentReactionTimeStepper::CalculateMinTimeStep",
|
||||
"G4DNAIndependentReactionTimeStepper006", FatalErrorInArgument,
|
||||
msg);
|
||||
G4Exception("G4DNAIndependentReactionTimeStepper::InitializeReactions",
|
||||
"G4DNAIndependentReactionTimeStepper030", FatalErrorInArgument, msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -374,36 +397,32 @@ G4double G4DNAIndependentReactionTimeStepper::CalculateMinTimeStep(G4double /*cu
|
||||
if (trackStatus == fStopAndKill || trackStatus == fStopButAlive) {
|
||||
continue;
|
||||
}
|
||||
|
||||
G4double sampledMinTimeStep = CalculateStep(*pTrack, definedMinTimeStep);
|
||||
G4TrackVectorHandle reactants = GetReactants();
|
||||
|
||||
if (sampledMinTimeStep < fTSTimeStep) {
|
||||
fTSTimeStep = sampledMinTimeStep;
|
||||
if (reactants) {
|
||||
fReactionSet->AddReactions(fTSTimeStep, const_cast<G4Track*>(pTrack), std::move(reactants));
|
||||
|
||||
fSampledPositions[pTrack->GetTrackID()] = pTrack->GetPosition();
|
||||
for (const auto& it : *fReactants) {
|
||||
auto pTrackB = it;
|
||||
fSampledPositions[pTrackB->GetTrackID()] = pTrackB->GetPosition();
|
||||
}
|
||||
ResetReactants();
|
||||
}
|
||||
}
|
||||
else if (fTSTimeStep == sampledMinTimeStep && G4bool(reactants)) {
|
||||
fReactionSet->AddReactions(fTSTimeStep, const_cast<G4Track*>(pTrack), std::move(reactants));
|
||||
|
||||
fSampledPositions[pTrack->GetTrackID()] = pTrack->GetPosition();
|
||||
for (const auto& it : *fReactants) {
|
||||
auto pTrackB = it;
|
||||
fSampledPositions[pTrackB->GetTrackID()] = pTrackB->GetPosition();
|
||||
}
|
||||
ResetReactants();
|
||||
}
|
||||
else if (reactants) {
|
||||
ResetReactants();
|
||||
}
|
||||
CalculateStep(*pTrack, fUserMinTimeStep);
|
||||
}
|
||||
return fTSTimeStep;
|
||||
if (fVerbose > 0)
|
||||
G4cout << "InitializeReactions : reaction events : "
|
||||
<< fReactionSet->GetReactionsPerTime().size() << ". The previous time step : "
|
||||
<< G4BestUnit(G4Scheduler::Instance()->GetPreviousTimeStep(), "Time") << G4endl;
|
||||
fIsInitialized = true;
|
||||
}
|
||||
|
||||
G4double G4DNAIndependentReactionTimeStepper::GetNextReactionTime()
|
||||
{
|
||||
G4double output = DBL_MAX;
|
||||
auto nextReaction = GetNextReaction();
|
||||
if (nextReaction != nullptr) {
|
||||
output = GetNextReaction()->GetTime();
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
const G4ITReaction* G4DNAIndependentReactionTimeStepper::GetNextReaction()
|
||||
{
|
||||
G4ITReaction* output = nullptr;
|
||||
G4ITReactionPerTime& reactionPerTime = fReactionSet->GetReactionsPerTime();
|
||||
auto reaction_i = reactionPerTime.begin();
|
||||
if (reaction_i != reactionPerTime.end()) {
|
||||
output = (reaction_i->get());
|
||||
}
|
||||
return output;
|
||||
}
|
||||
@@ -37,6 +37,8 @@
|
||||
#include "G4DNAIndependentReactionTimeStepper.hh"
|
||||
#include "G4Scheduler.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
#include "G4DNAScavengerMaterial.hh"
|
||||
#include "G4MoleculeCounterManager.hh"
|
||||
|
||||
G4DNAMakeReaction::G4DNAMakeReaction()
|
||||
:
|
||||
@@ -45,6 +47,8 @@ G4DNAMakeReaction::G4DNAMakeReaction()
|
||||
, fpTimeStepper(nullptr)
|
||||
, fTimeStep(0)
|
||||
{
|
||||
fpScavengerMaterial = dynamic_cast<G4DNAScavengerMaterial*>(
|
||||
G4Scheduler::Instance()->GetScavengerMaterial());
|
||||
}
|
||||
|
||||
G4DNAMakeReaction::G4DNAMakeReaction(G4VDNAReactionModel* pReactionModel)
|
||||
@@ -83,6 +87,10 @@ G4DNAMakeReaction::MakeReaction(const G4Track &trackA,
|
||||
|
||||
const auto pReactionData = fMolReactionTable->GetReactionData(pMoleculeA, pMoleculeB);
|
||||
const G4int nbProducts = pReactionData->GetNbProducts();
|
||||
// Notify molecule (reaction) counter
|
||||
if (G4MoleculeCounterManager::Instance()->GetIsActive()) {
|
||||
G4MoleculeCounterManager::Instance()->RecordReaction(pReactionData, trackA.GetGlobalTime());
|
||||
}
|
||||
if (nbProducts != 0)
|
||||
{
|
||||
const G4double D1 = pMoleculeA->GetDiffusionCoefficient();
|
||||
@@ -98,7 +106,18 @@ G4DNAMakeReaction::MakeReaction(const G4Track &trackA,
|
||||
|
||||
for (G4int j = 0; j < nbProducts; ++j)
|
||||
{
|
||||
auto pProduct = new G4Molecule(pReactionData->GetProduct(j));
|
||||
auto product = pReactionData->GetProduct(j);
|
||||
|
||||
if(fpScavengerMaterial != nullptr) {
|
||||
auto isScavenger = fpScavengerMaterial->find(product);
|
||||
if (isScavenger) {
|
||||
fpScavengerMaterial->AddNumberMoleculePerVolumeUnitForMaterialConf(
|
||||
product, trackA.GetGlobalTime());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
auto pProduct = new G4Molecule(product);
|
||||
auto pProductTrack = pProduct->BuildTrack(trackA.GetGlobalTime(), (reactionSite + randP)/2);
|
||||
pProductTrack->SetTrackStatus(fAlive);
|
||||
G4ITTrackHolder::Instance()->Push(pProductTrack);
|
||||
@@ -181,27 +200,30 @@ void G4DNAMakeReaction::UpdatePositionForReaction(G4Track& trackA,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::unique_ptr<G4ITReactionChange>>
|
||||
G4DNAMakeReaction::FindReaction(G4ITReactionSet* pReactionSet,
|
||||
const G4double currentStepTime,
|
||||
const G4double /*globalTime*/,
|
||||
const G4double globalTime,
|
||||
const G4bool /*reachedUserStepTimeLimit*/)
|
||||
{
|
||||
std::vector<std::unique_ptr<G4ITReactionChange>> ReactionInfo;
|
||||
ReactionInfo.clear();
|
||||
auto stepper = dynamic_cast<G4DNAIndependentReactionTimeStepper*>(fpTimeStepper);
|
||||
if(stepper == nullptr){
|
||||
return ReactionInfo;
|
||||
}else
|
||||
{
|
||||
do{
|
||||
auto pReactionChange = stepper->
|
||||
FindReaction(pReactionSet,currentStepTime);
|
||||
if (pReactionChange != nullptr)
|
||||
{
|
||||
ReactionInfo.push_back(std::move(pReactionChange));
|
||||
}
|
||||
}while (!pReactionSet->GetReactionsPerTime().empty());
|
||||
}
|
||||
std::vector<std::unique_ptr<G4ITReactionChange>> ReactionInfo;
|
||||
auto stepper = dynamic_cast<G4DNAIndependentReactionTimeStepper*>(fpTimeStepper);
|
||||
if (stepper == nullptr) {
|
||||
return ReactionInfo;
|
||||
}else {
|
||||
G4double StepTime = 0;
|
||||
do {
|
||||
auto pReactionChange = stepper->FindReaction(pReactionSet, StepTime, globalTime);
|
||||
if (pReactionChange != nullptr) {
|
||||
// G4cout<<" time : "<<globalTime<<" "<<pReactionChange->GetTrackA()->GetTrackID()
|
||||
// <<" + "<<pReactionChange->GetTrackB()->GetTrackID()<<G4endl;
|
||||
ReactionInfo.push_back(std::move(pReactionChange));
|
||||
}
|
||||
else{
|
||||
break;
|
||||
}
|
||||
}while(StepTime == currentStepTime);
|
||||
}
|
||||
return ReactionInfo;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "G4ITReaction.hh"
|
||||
|
||||
#include "G4ITTrackHolder.hh"
|
||||
#include "G4MoleculeCounterManager.hh"
|
||||
|
||||
G4DNAMolecularReaction::G4DNAMolecularReaction()
|
||||
:
|
||||
@@ -91,7 +92,10 @@ std::unique_ptr<G4ITReactionChange> G4DNAMolecularReaction::MakeReaction(const G
|
||||
const auto pMoleculeB = GetMolecule(trackB)->GetMolecularConfiguration();
|
||||
|
||||
const auto pReactionData = fMolReactionTable->GetReactionData(pMoleculeA, pMoleculeB);
|
||||
|
||||
// Notify molecule (reaction) counter
|
||||
if (G4MoleculeCounterManager::Instance()->GetIsActive()) {
|
||||
G4MoleculeCounterManager::Instance()->RecordReaction(pReactionData, trackA.GetGlobalTime());
|
||||
}
|
||||
const G4int nbProducts = pReactionData->GetNbProducts();
|
||||
|
||||
if (nbProducts != 0)
|
||||
|
||||
@@ -0,0 +1,556 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// Created 11.02.2025 V.Ivanchenko & M. Vologzhin
|
||||
// on base of previous Rudd models
|
||||
//
|
||||
// Russian Goverment grant No 075-15-2024-667 23.08.2024
|
||||
//
|
||||
|
||||
#include "G4DNARuddIonisationDynamicModel.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4VAtomDeexcitation.hh"
|
||||
#include "G4UAtomicDeexcitation.hh"
|
||||
#include "G4LossTableManager.hh"
|
||||
#include "G4NistManager.hh"
|
||||
#include "G4DNAChemistryManager.hh"
|
||||
#include "G4DNAMolecularMaterial.hh"
|
||||
#include "G4LogLogInterpolation.hh"
|
||||
#include "G4ProductionCutsTable.hh"
|
||||
|
||||
#include "G4DNAGenericIonsManager.hh"
|
||||
#include "G4DNACrossSectionDataSet.hh"
|
||||
#include "G4NistManager.hh"
|
||||
|
||||
#include "G4IonTable.hh"
|
||||
#include "G4DNARuddAngle.hh"
|
||||
#include "G4DeltaAngle.hh"
|
||||
#include "G4Exp.hh"
|
||||
#include "G4Log.hh"
|
||||
#include "G4Pow.hh"
|
||||
#include "G4Alpha.hh"
|
||||
#include "G4Proton.hh"
|
||||
#include "G4Electron.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DNACrossSectionDataSet* G4DNARuddIonisationDynamicModel::xsdata_hydrogen = nullptr;
|
||||
G4DNACrossSectionDataSet* G4DNARuddIonisationDynamicModel::xsdata_helium = nullptr;
|
||||
G4DNACrossSectionDataSet* G4DNARuddIonisationDynamicModel::xsdata_p = nullptr;
|
||||
const std::vector<G4double>* G4DNARuddIonisationDynamicModel::fpWaterDensity = nullptr;
|
||||
|
||||
namespace
|
||||
{
|
||||
const G4double scaleFactor = CLHEP::m*CLHEP::m;
|
||||
const G4double tolerance = 1*CLHEP::eV;
|
||||
const G4double Ry = 13.6*CLHEP::eV;
|
||||
|
||||
// Following values provided by M. Dingfelder (priv. comm)
|
||||
const G4double Bj[5] = {12.60*CLHEP::eV, 14.70*CLHEP::eV, 18.40*CLHEP::eV,
|
||||
32.20*CLHEP::eV, 539*CLHEP::eV};
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DNARuddIonisationDynamicModel::G4DNARuddIonisationDynamicModel(const G4ParticleDefinition*,
|
||||
const G4String& nam)
|
||||
: G4VEmModel(nam)
|
||||
{
|
||||
fGpow = G4Pow::GetInstance();
|
||||
fLowestEnergy = 100*CLHEP::eV;
|
||||
fAbsorptionEnergy = 50*CLHEP::eV;
|
||||
|
||||
// Mark this model as "applicable" for atomic deexcitation
|
||||
SetDeexcitationFlag(true);
|
||||
|
||||
// Define default angular generator
|
||||
SetAngularDistribution(new G4DNARuddAngle());
|
||||
|
||||
if (nullptr == xsdata_p) {
|
||||
isFirst = true;
|
||||
LoadData();
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DNARuddIonisationDynamicModel::~G4DNARuddIonisationDynamicModel()
|
||||
{
|
||||
if (isFirst) {
|
||||
delete xsdata_p;
|
||||
delete xsdata_hydrogen;
|
||||
delete xsdata_helium;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNARuddIonisationDynamicModel::LoadData()
|
||||
{
|
||||
// initialisation of static data once
|
||||
G4String filename = "dna/sigma_ionisation_p_rudd";
|
||||
xsdata_p = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor);
|
||||
xsdata_p->LoadData(filename);
|
||||
|
||||
filename = "dna/sigma_ionisation_h_rudd";
|
||||
xsdata_hydrogen = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor);
|
||||
xsdata_hydrogen->LoadData(filename);
|
||||
|
||||
filename = "dna/sigma_ionisation_he_rudd";
|
||||
xsdata_helium = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor);
|
||||
xsdata_helium->LoadData(filename);
|
||||
|
||||
// to avoid possible threading problem fill this vector only once
|
||||
auto water = G4NistManager::Instance()->FindMaterial("G4_WATER");
|
||||
fpWaterDensity =
|
||||
G4DNAMolecularMaterial::Instance()->GetNumMolPerVolTableFor(water);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNARuddIonisationDynamicModel::Initialise(const G4ParticleDefinition* p,
|
||||
const G4DataVector&)
|
||||
{
|
||||
if (p != fParticle) { SetParticle(p); }
|
||||
|
||||
// particle change object may be externally set
|
||||
if (nullptr == fParticleChangeForGamma) {
|
||||
fParticleChangeForGamma = GetParticleChangeForGamma();
|
||||
}
|
||||
const G4String& pname = p->GetParticleName();
|
||||
|
||||
// the same definition of generic ion as in G4VEmProcess class
|
||||
if (p->GetParticleType() == "nucleus" && p->GetParticleSubType() == "generic") {
|
||||
if (pname != "deuteron" && pname != "triton" &&
|
||||
pname != "He3" && pname != "alpha" && pname != "alpha+" &&
|
||||
pname != "helium" && pname != "hydrogen") {
|
||||
isIon = true;
|
||||
}
|
||||
}
|
||||
|
||||
// initialisation once in each thread
|
||||
if (!isInitialised) {
|
||||
isInitialised = true;
|
||||
xsdata = xsdata_p;
|
||||
|
||||
if (pname == "helium") {
|
||||
isHelium = true;
|
||||
xsdata = xsdata_helium;
|
||||
slaterEffectiveCharge[0]=1.7;
|
||||
slaterEffectiveCharge[1]=1.15;
|
||||
slaterEffectiveCharge[2]=1.15;
|
||||
sCoefficient[0]=0.5;
|
||||
sCoefficient[1]=0.25;
|
||||
sCoefficient[2]=0.25;
|
||||
fLowestEnergy = 1*CLHEP::keV;
|
||||
} else if (pname == "alpha+") {
|
||||
isHelium = true;
|
||||
// The following values are provided by M. Dingfelder (priv. comm)
|
||||
slaterEffectiveCharge[0]=2.0;
|
||||
slaterEffectiveCharge[1]=2.0;
|
||||
slaterEffectiveCharge[2]=2.0;
|
||||
sCoefficient[0]=0.7;
|
||||
sCoefficient[1]=0.15;
|
||||
sCoefficient[2]=0.15;
|
||||
} else if (pname == "hydrogen") {
|
||||
xsdata = xsdata_hydrogen;
|
||||
}
|
||||
|
||||
// defined stationary mode
|
||||
statCode = G4EmParameters::Instance()->DNAStationary();
|
||||
|
||||
// initialise atomic de-excitation
|
||||
if (!statCode)
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
|
||||
// chemistry
|
||||
auto chem = G4DNAChemistryManager::Instance();
|
||||
if (chem->IsChemistryActivated()) {
|
||||
fChemistry = chem;
|
||||
}
|
||||
|
||||
InitialiseIntegrator(0.1, 0.25, 1.05, 1*CLHEP::eV, 0.2*CLHEP::eV, 10*CLHEP::keV);
|
||||
|
||||
if (verbose > 0) {
|
||||
G4cout << "### G4DNARuddIonisationDynamicModel::Initialise(..) "
|
||||
<< fParticle->GetParticleName() << G4endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNARuddIonisationDynamicModel::SetParticle(const G4ParticleDefinition* p)
|
||||
{
|
||||
fParticle = p;
|
||||
fMass = p->GetPDGMass();
|
||||
fMassRate = CLHEP::proton_mass_c2/fMass;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNARuddIonisationDynamicModel::StartTracking(G4Track* track)
|
||||
{
|
||||
fTrack = track;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double
|
||||
G4DNARuddIonisationDynamicModel::CrossSectionPerVolume(const G4Material* material,
|
||||
const G4ParticleDefinition* part,
|
||||
G4double kinE,
|
||||
G4double, G4double)
|
||||
{
|
||||
// check if model is applicable for given material
|
||||
G4double density = (material->GetIndex() < fpWaterDensity->size())
|
||||
? (*fpWaterDensity)[material->GetIndex()] : 0.0;
|
||||
if (0.0 == density) { return 0.0; }
|
||||
|
||||
// check on kinetic energy (not scaled energy) to stop low-energy ion
|
||||
if (kinE < fAbsorptionEnergy) { return DBL_MAX; }
|
||||
|
||||
// ion may be different
|
||||
if (fParticle != part) { SetParticle(part); }
|
||||
G4double q = fTrack->GetDynamicParticle()->GetCharge()*inveplus;
|
||||
|
||||
// cross section for scaled energy
|
||||
G4double e = kinE*fMassRate;
|
||||
|
||||
auto xs = xsdata;
|
||||
if (0.0 == q) { xs = isHelium ? xsdata_helium : xsdata_hydrogen; }
|
||||
|
||||
G4double sigma = (e > fLowestEnergy) ? xs->FindValue(e)
|
||||
: xs->FindValue(fLowestEnergy) * e / fLowestEnergy;
|
||||
|
||||
sigma *= density;
|
||||
if (q > 1.5) { sigma *= q * q; }
|
||||
|
||||
if (verbose > 1) {
|
||||
G4cout << "G4DNARuddIonisationDynamicModel for " << part->GetParticleName()
|
||||
<< " Ekin(keV)=" << kinE/CLHEP::keV
|
||||
<< " sigma(cm^2)=" << sigma/CLHEP::cm2 << G4endl;
|
||||
}
|
||||
return sigma;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void
|
||||
G4DNARuddIonisationDynamicModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
|
||||
const G4MaterialCutsCouple* couple,
|
||||
const G4DynamicParticle* dpart,
|
||||
G4double, G4double)
|
||||
{
|
||||
const G4ParticleDefinition* pd = dpart->GetDefinition();
|
||||
if (fParticle != pd) { SetParticle(pd); }
|
||||
|
||||
// stop ion with energy below low energy limit
|
||||
G4double kinE = dpart->GetKineticEnergy();
|
||||
// ion shoud be stopped - check on kinetic energy and not scaled energy
|
||||
if (kinE <= fAbsorptionEnergy) {
|
||||
fParticleChangeForGamma->SetProposedKineticEnergy(0.);
|
||||
fParticleChangeForGamma->ProposeTrackStatus(fStopButAlive);
|
||||
fParticleChangeForGamma->ProposeLocalEnergyDeposit(kinE);
|
||||
return;
|
||||
}
|
||||
|
||||
fScaledEnergy = kinE*fMassRate;
|
||||
fSelectedShell = SelectShell();
|
||||
G4double bindingEnergy = (useDNAWaterStructure)
|
||||
? waterStructure.IonisationEnergy(fSelectedShell) : Bj[fSelectedShell];
|
||||
|
||||
//Si: additional protection if tcs interpolation method is modified
|
||||
if (kinE < bindingEnergy) { return; }
|
||||
|
||||
G4double esec = SampleElectronEnergy();
|
||||
G4double esum = 0.0;
|
||||
|
||||
// sample deexcitation
|
||||
// here we assume that H2O electronic levels are the same as Oxygen.
|
||||
// this can be considered true with a rough 10% error in energy on K-shell,
|
||||
G4int Z = 8;
|
||||
G4ThreeVector deltaDir =
|
||||
GetAngularDistribution()->SampleDirectionForShell(dpart, esec, Z,
|
||||
fSelectedShell,
|
||||
couple->GetMaterial());
|
||||
|
||||
// SI: only atomic deexcitation from K shell is considered
|
||||
if (fAtomDeexcitation != nullptr && fSelectedShell == 4) {
|
||||
auto as = G4AtomicShellEnumerator(0);
|
||||
auto ashell = fAtomDeexcitation->GetAtomicShell(Z, as);
|
||||
fAtomDeexcitation->GenerateParticles(fvect, ashell, Z, 0, 0);
|
||||
|
||||
// compute energy sum from de-excitation
|
||||
for (auto const & ptr : *fvect) {
|
||||
esum += ptr->GetKineticEnergy();
|
||||
}
|
||||
}
|
||||
// check energy balance
|
||||
// remaining excitation energy of water molecule
|
||||
G4double exc = std::max(bindingEnergy - esum, 0.0);
|
||||
|
||||
// remaining projectile energy
|
||||
G4double scatteredEnergy = kinE - bindingEnergy - esec;
|
||||
if(scatteredEnergy < -tolerance || exc < -tolerance) {
|
||||
G4cout << "G4DNARuddIonisationDynamicModel::SampleSecondaries: "
|
||||
<< "negative final E(keV)=" << scatteredEnergy/CLHEP::keV << " Ein(keV)="
|
||||
<< kinE/CLHEP::keV << " " << pd->GetParticleName()
|
||||
<< " Edelta(keV)=" << esec/CLHEP::keV << " MeV, Exc(keV)=" << exc/CLHEP::keV
|
||||
<< G4endl;
|
||||
}
|
||||
scatteredEnergy = std::max(scatteredEnergy, 0.0);
|
||||
|
||||
// projectile
|
||||
if (!statCode) {
|
||||
fParticleChangeForGamma->SetProposedKineticEnergy(scatteredEnergy);
|
||||
fParticleChangeForGamma->ProposeLocalEnergyDeposit(exc);
|
||||
} else {
|
||||
fParticleChangeForGamma->SetProposedKineticEnergy(kinE);
|
||||
fParticleChangeForGamma->ProposeLocalEnergyDeposit(kinE - scatteredEnergy);
|
||||
}
|
||||
|
||||
// delta-electron
|
||||
auto dp = new G4DynamicParticle(G4Electron::Electron(), deltaDir, esec);
|
||||
fvect->push_back(dp);
|
||||
|
||||
// create radical
|
||||
if (nullptr != fChemistry) {
|
||||
fChemistry->CreateWaterMolecule(eIonizedMolecule, fSelectedShell, fTrack);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4int G4DNARuddIonisationDynamicModel::SelectShell()
|
||||
{
|
||||
G4double sum = 0.0;
|
||||
G4double xs;
|
||||
for (G4int i=0; i<5; ++i) {
|
||||
auto ptr = xsdata->GetComponent(i);
|
||||
xs = (fScaledEnergy > fLowestEnergy) ? ptr->FindValue(fScaledEnergy)
|
||||
: ptr->FindValue(fLowestEnergy)*fScaledEnergy/fLowestEnergy;
|
||||
sum += xs;
|
||||
fTemp[i] = sum;
|
||||
}
|
||||
sum *= G4UniformRand();
|
||||
for (G4int i=0; i<5; ++i) {
|
||||
if (sum <= fTemp[i]) { return i; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double
|
||||
G4DNARuddIonisationDynamicModel::MaxEnergy()
|
||||
{
|
||||
// kinematic limit
|
||||
G4double tau = fScaledEnergy/CLHEP::proton_mass_c2;
|
||||
G4double gam = 1.0 + tau;
|
||||
G4double emax = 2.0*CLHEP::electron_mass_c2*tau*(tau + 2.0);
|
||||
|
||||
// Initialisation of sampling
|
||||
G4double A1, B1, C1, D1, E1, A2, B2, C2, D2;
|
||||
if (fSelectedShell == 4) {
|
||||
//Data For Liquid Water K SHELL from Dingfelder (Protons in Water)
|
||||
A1 = 1.25;
|
||||
B1 = 0.5;
|
||||
C1 = 1.00;
|
||||
D1 = 1.00;
|
||||
E1 = 3.00;
|
||||
A2 = 1.10;
|
||||
B2 = 1.30;
|
||||
C2 = 1.00;
|
||||
D2 = 0.00;
|
||||
alphaConst = 0.66;
|
||||
} else {
|
||||
//Data For Liquid Water from Dingfelder (Protons in Water)
|
||||
A1 = 1.02;
|
||||
B1 = 82.0;
|
||||
C1 = 0.45;
|
||||
D1 = -0.80;
|
||||
E1 = 0.38;
|
||||
A2 = 1.07;
|
||||
// Value provided by M. Dingfelder (priv. comm)
|
||||
B2 = 11.6;
|
||||
C2 = 0.60;
|
||||
D2 = 0.04;
|
||||
alphaConst = 0.64;
|
||||
}
|
||||
bEnergy = Bj[fSelectedShell];
|
||||
G4double v2 = 0.25*emax/(bEnergy*gam*gam);
|
||||
v = std::sqrt(v2);
|
||||
u = Ry/bEnergy;
|
||||
wc = 4.*v2 - 2.*v - 0.25*u;
|
||||
|
||||
G4double L1 = (C1 * fGpow->powA(v, D1)) / (1. + E1 * fGpow->powA(v, (D1 + 4.)));
|
||||
G4double L2 = C2 * fGpow->powA(v, D2);
|
||||
G4double H1 = (A1 * G4Log(1. + v2)) / (v2 + (B1 / v2));
|
||||
G4double H2 = (A2 / v2) + (B2 / (v2 * v2));
|
||||
|
||||
F1 = L1 + H1;
|
||||
F2 = (L2 * H2) / (L2 + H2);
|
||||
return emax;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double
|
||||
G4DNARuddIonisationDynamicModel::SampleElectronEnergy()
|
||||
{
|
||||
// sampling is performed for proton projectile
|
||||
G4double emax = MaxEnergy();
|
||||
|
||||
ComputeIntegral(0.0, emax);
|
||||
G4double e = SampleValue();
|
||||
if (verbose > 1) {
|
||||
G4cout << "G4DNARuddIonisationDynamicModel::SampleElectronEnergy: "
|
||||
<< fParticle->GetParticleName()
|
||||
<< " Escaled(keV)=" << fScaledEnergy/CLHEP::keV << " Ee(keV)=" << e/CLHEP::keV
|
||||
<< G4endl;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4DNARuddIonisationDynamicModel::ProbabilityDensityFunction(G4double e)
|
||||
{
|
||||
// Shells ids are 0 1 2 3 4 (4 is k shell)
|
||||
// !!Attention, "energyTransfer" here is the energy transfered to the electron which means
|
||||
// that the secondary kinetic energy is w = energyTransfer - bindingEnergy
|
||||
//
|
||||
// ds S F1(nu) + w * F2(nu)
|
||||
// ---- = G(k) * ---- -------------------------------------------
|
||||
// dw Bj (1+w)^3 * [1 + exp{alpha * (w - wc) / nu}]
|
||||
//
|
||||
// w is the secondary electron kinetic Energy in eV
|
||||
//
|
||||
// All the other parameters can be found in Rudd's Papers
|
||||
//
|
||||
// M.Eugene Rudd, 1988, User-Friendly model for the energy distribution of
|
||||
// electrons from protons or electron collisions. Nucl. Tracks Rad. Meas.Vol 16 N0 2/3 pp 219-218
|
||||
//
|
||||
G4double w = e/bEnergy;
|
||||
G4double x = alphaConst*(w - wc)/v;
|
||||
G4double y = (x > -15.) ? 1.0 + G4Exp(x) : 1.0;
|
||||
|
||||
G4double res = CorrectionFactor() * (F1 + w*F2) /
|
||||
(fGpow->powN((1. + w)/u, 3) * y);
|
||||
|
||||
if (isHelium) {
|
||||
G4double energyTransfer = e + bEnergy;
|
||||
G4double Zeff = 2.0 -
|
||||
(sCoefficient[0] * S_1s(fScaledEnergy, energyTransfer, slaterEffectiveCharge[0], 1.) +
|
||||
sCoefficient[1] * S_2s(fScaledEnergy, energyTransfer, slaterEffectiveCharge[1], 2.) +
|
||||
sCoefficient[2] * S_2p(fScaledEnergy, energyTransfer, slaterEffectiveCharge[2], 2.) );
|
||||
|
||||
res *= Zeff * Zeff;
|
||||
}
|
||||
return std::max(res, 0.0);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4DNARuddIonisationDynamicModel::S_1s(G4double kine,
|
||||
G4double energyTransfer,
|
||||
G4double slaterEffCharge,
|
||||
G4double shellNumber)
|
||||
{
|
||||
// 1 - e^(-2r) * ( 1 + 2 r + 2 r^2)
|
||||
// Dingfelder, in Chattanooga 2005 proceedings, formula (7)
|
||||
|
||||
G4double r = Rh(kine, energyTransfer, slaterEffCharge, shellNumber);
|
||||
G4double value = 1. - G4Exp(-2 * r) * ( ( 2. * r + 2. ) * r + 1. );
|
||||
return value;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4DNARuddIonisationDynamicModel::S_2s(G4double kine,
|
||||
G4double energyTransfer,
|
||||
G4double slaterEffCharge,
|
||||
G4double shellNumber)
|
||||
{
|
||||
// 1 - e^(-2 r) * ( 1 + 2 r + 2 r^2 + 2 r^4)
|
||||
// Dingfelder, in Chattanooga 2005 proceedings, formula (8)
|
||||
|
||||
G4double r = Rh(kine, energyTransfer, slaterEffCharge, shellNumber);
|
||||
G4double value =
|
||||
1. - G4Exp(-2 * r) * (((2. * r * r + 2.) * r + 2.) * r + 1.);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4DNARuddIonisationDynamicModel::S_2p(G4double kine,
|
||||
G4double energyTransfer,
|
||||
G4double slaterEffCharge,
|
||||
G4double shellNumber)
|
||||
{
|
||||
// 1 - e^(-2 r) * ( 1 + 2 r + 2 r^2 + 4/3 r^3 + 2/3 r^4)
|
||||
// Dingfelder, in Chattanooga 2005 proceedings, formula (9)
|
||||
|
||||
G4double r = Rh(kine, energyTransfer, slaterEffCharge, shellNumber);
|
||||
G4double value =
|
||||
1. - G4Exp(-2 * r) * (((( 2./3. * r + 4./3.) * r + 2.) * r + 2.) * r + 1.);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4DNARuddIonisationDynamicModel::Rh(G4double ekin, G4double etrans,
|
||||
G4double q, G4double shell)
|
||||
{
|
||||
// The following values are provided by M. Dingfelder (priv. comm)
|
||||
// Dingfelder, in Chattanooga 2005 proceedings, p 4
|
||||
|
||||
G4double escaled = CLHEP::electron_mass_c2/fMass * ekin;
|
||||
const G4double H = 13.60569172 * CLHEP::eV;
|
||||
G4double value = 2.0*std::sqrt(escaled / H)*q*H /(etrans*shell);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4DNARuddIonisationDynamicModel::CorrectionFactor()
|
||||
{
|
||||
// ZF Shortened
|
||||
G4double res = 1.0;
|
||||
if (fSelectedShell < 4) {
|
||||
const G4double ln10 = fGpow->logZ(10);
|
||||
G4double x = 2.0*((G4Log(fScaledEnergy/CLHEP::eV)/ln10) - 4.2);
|
||||
// The following values are provided by M. Dingfelder (priv. comm)
|
||||
res = 0.6/(1.0 + G4Exp(x)) + 0.9;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
@@ -91,7 +91,7 @@ G4DNARuddIonisationExtendedModel::G4DNARuddIonisationExtendedModel(const G4Parti
|
||||
|
||||
G4DNARuddIonisationExtendedModel::~G4DNARuddIonisationExtendedModel()
|
||||
{
|
||||
if(isFirst) {
|
||||
if (isFirst) {
|
||||
for(auto & i : xsdata) { delete i; }
|
||||
}
|
||||
}
|
||||
@@ -222,7 +222,8 @@ void G4DNARuddIonisationExtendedModel::Initialise(const G4ParticleDefinition* p,
|
||||
statCode = G4EmParameters::Instance()->DNAStationary();
|
||||
|
||||
// initialise atomic de-excitation
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
if (!statCode)
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
|
||||
if (verbose > 0) {
|
||||
G4cout << "### G4DNARuddIonisationExtendedModel::Initialise(..) " << pname
|
||||
@@ -330,17 +331,18 @@ G4DNARuddIonisationExtendedModel::SampleSecondaries(std::vector<G4DynamicParticl
|
||||
}
|
||||
// check energy balance
|
||||
// remaining excitation energy of water molecule
|
||||
G4double exc = bindingEnergy - esum;
|
||||
G4double exc = std::max(bindingEnergy - esum, 0.0);
|
||||
|
||||
// remaining projectile energy
|
||||
G4double scatteredEnergy = kinE - bindingEnergy - esec;
|
||||
if(scatteredEnergy < -tolerance || exc < -tolerance) {
|
||||
if (scatteredEnergy < -tolerance || exc < -tolerance) {
|
||||
G4cout << "G4DNARuddIonisationExtendedModel::SampleSecondaries: "
|
||||
<< "negative final E(keV)=" << scatteredEnergy/CLHEP::keV << " Ein(keV)="
|
||||
<< kinE/CLHEP::keV << " " << pd->GetParticleName()
|
||||
<< " Edelta(keV)=" << esec/CLHEP::keV << " MeV, Exc(keV)=" << exc/CLHEP::keV
|
||||
<< G4endl;
|
||||
}
|
||||
scatteredEnergy = std::max(scatteredEnergy, 0.0);
|
||||
|
||||
// projectile
|
||||
if (!statCode) {
|
||||
|
||||
@@ -258,7 +258,22 @@ void G4DNARuddIonisationModel::Initialise(const G4ParticleDefinition* particle,
|
||||
SetHighEnergyLimit(highEnergyLimit[alphaPlusPlus]);
|
||||
}
|
||||
|
||||
if( verboseLevel>0 )
|
||||
if (isInitialised) { return; }
|
||||
|
||||
// defined stationary mode
|
||||
statCode = G4EmParameters::Instance()->DNAStationary();
|
||||
|
||||
// Initialize water density pointer
|
||||
fpWaterDensity = G4DNAMolecularMaterial::Instance()->GetNumMolPerVolTableFor(G4Material::GetMaterial("G4_WATER"));
|
||||
|
||||
// atomic de-excitation
|
||||
if (!statCode)
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
|
||||
fParticleChangeForGamma = GetParticleChangeForGamma();
|
||||
isInitialised = true;
|
||||
|
||||
if (verboseLevel > 0)
|
||||
{
|
||||
G4cout << "Rudd ionisation model is initialized " << G4endl
|
||||
<< "Energy range: "
|
||||
@@ -267,19 +282,6 @@ void G4DNARuddIonisationModel::Initialise(const G4ParticleDefinition* particle,
|
||||
<< particle->GetParticleName()
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
// Initialize water density pointer
|
||||
fpWaterDensity = G4DNAMolecularMaterial::Instance()->GetNumMolPerVolTableFor(G4Material::GetMaterial("G4_WATER"));
|
||||
|
||||
//
|
||||
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
|
||||
if (isInitialised)
|
||||
{ return;}
|
||||
fParticleChangeForGamma = GetParticleChangeForGamma();
|
||||
isInitialised = true;
|
||||
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#include "G4DNAScavengerMaterial.hh"
|
||||
#include "G4Scheduler.hh"
|
||||
|
||||
#include "G4MoleculeCounterManager.hh"
|
||||
|
||||
G4DNAUpdateSystemModel::G4DNAUpdateSystemModel() = default;
|
||||
|
||||
void G4DNAUpdateSystemModel::SetMesh(G4DNAMesh* pMesh) { fpMesh = pMesh; }
|
||||
@@ -53,9 +55,9 @@ void G4DNAUpdateSystemModel::KillMolecule(const Index& index, MolType type)
|
||||
FatalErrorInArgument, exceptionDescription);
|
||||
}
|
||||
iter->second--;
|
||||
if(G4VMoleculeCounter::Instance()->InUse())
|
||||
if (G4MoleculeCounterManager::Instance()->GetIsActive())
|
||||
{
|
||||
G4VMoleculeCounter::Instance()->RemoveAMoleculeAtTime(type, fGlobalTime);
|
||||
G4MoleculeCounterManager::Instance()->RemoveMoleculeWithoutTrack(type, fGlobalTime);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -131,9 +133,9 @@ void G4DNAUpdateSystemModel::CreateMolecule(const Index& index, MolType type)
|
||||
node[type] = 1;
|
||||
}
|
||||
|
||||
if(G4VMoleculeCounter::Instance()->InUse())
|
||||
if (G4MoleculeCounterManager::Instance()->GetIsActive())
|
||||
{
|
||||
G4VMoleculeCounter::Instance()->AddAMoleculeAtTime(type, fGlobalTime);
|
||||
G4MoleculeCounterManager::Instance()->AddMoleculeWithoutTrack(type, fGlobalTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -205,7 +205,7 @@ public:
|
||||
*/
|
||||
void PrintState() const;
|
||||
|
||||
G4Track * BuildTrack(G4double globalTime, const G4ThreeVector& Position);
|
||||
G4Track* BuildTrack(G4double globalTime, const G4ThreeVector &Position, const G4Track * = nullptr);
|
||||
|
||||
G4double GetKineticEnergy() const;
|
||||
|
||||
|
||||
+50
-98
@@ -24,14 +24,15 @@
|
||||
// ********************************************************************
|
||||
//
|
||||
// Author: Mathieu Karamitros
|
||||
// Modified by Christian Velten (2024)
|
||||
|
||||
// The code is developed in the framework of the ESA AO7146
|
||||
//
|
||||
// We would be very happy hearing from you, send us your feedback! :)
|
||||
//
|
||||
// In order for Geant4-DNA to be maintained and still open-source,
|
||||
// article citations are crucial.
|
||||
// If you use Geant4-DNA chemistry and you publish papers about your software,
|
||||
// article citations are crucial.
|
||||
// If you use Geant4-DNA chemistry and you publish papers about your software,
|
||||
// in addition to the general paper on Geant4-DNA:
|
||||
//
|
||||
// Int. J. Model. Simul. Sci. Comput. 1 (2010) 157–178
|
||||
@@ -40,111 +41,62 @@
|
||||
// reference papers on chemistry:
|
||||
//
|
||||
// J. Comput. Phys. 274 (2014) 841-882
|
||||
// Prog. Nucl. Sci. Tec. 2 (2011) 503-508
|
||||
// Prog. Nucl. Sci. Tec. 2 (2011) 503-508
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "G4VMoleculeCounter.hh"
|
||||
#include "G4MolecularConfiguration.hh"
|
||||
#include "G4VUserMoleculeCounter.hh"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace G4 {
|
||||
namespace MoleculeCounter {
|
||||
struct TimePrecision
|
||||
struct G4MoleculeCounterIndex : public G4VMoleculeCounter::G4VMoleculeCounterIndex
|
||||
{
|
||||
bool operator()(const double& a, const double& b) const;
|
||||
static G4ThreadLocal double fPrecision;
|
||||
};
|
||||
}
|
||||
}
|
||||
using NbMoleculeAgainstTime = std::map<G4double, G4int, G4::MoleculeCounter::TimePrecision>;
|
||||
using RecordedTimes = std::unique_ptr<std::set<G4double>>;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class G4MoleculeCounter : public G4VMoleculeCounter
|
||||
{
|
||||
//----------------------------------------------------------------------------
|
||||
public:
|
||||
using ReactantList = std::vector<Reactant*>;
|
||||
using CounterMapType = std::map<Reactant*, NbMoleculeAgainstTime>;
|
||||
using RecordedMolecules = std::unique_ptr<ReactantList>;
|
||||
|
||||
static G4MoleculeCounter* Instance();
|
||||
|
||||
void Initialize() override;
|
||||
void ResetCounter() override;
|
||||
|
||||
/* The dynamics of the given molecule won't be saved into memory.*/
|
||||
void DontRegister(const G4MoleculeDefinition*) override;
|
||||
bool IsRegistered(const G4MoleculeDefinition*) override;
|
||||
void RegisterAll() override;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
int GetNMoleculesAtTime(Reactant* molecule, double time);
|
||||
const NbMoleculeAgainstTime& GetNbMoleculeAgainstTime(Reactant* molecule);
|
||||
|
||||
RecordedMolecules GetRecordedMolecules();
|
||||
RecordedTimes GetRecordedTimes();
|
||||
|
||||
void SetVerbose(G4int);
|
||||
G4int GetVerbose();
|
||||
|
||||
/* It sets the min time difference in between two time slices. */
|
||||
static void SetTimeSlice(double);
|
||||
|
||||
void Dump();
|
||||
|
||||
G4bool IsTimeCheckedForConsistency() const;
|
||||
void CheckTimeForConsistency(G4bool flag);
|
||||
|
||||
#ifdef MOLECULE_COUNTER_TESTING
|
||||
public:
|
||||
#else
|
||||
protected:
|
||||
#endif
|
||||
void AddAMoleculeAtTime(Reactant*,
|
||||
G4double time,
|
||||
const G4ThreeVector* position = nullptr,
|
||||
int number = 1) override;
|
||||
void RemoveAMoleculeAtTime(Reactant*,
|
||||
G4double time,
|
||||
const G4ThreeVector* position = nullptr,
|
||||
int number = 1) override;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
protected:
|
||||
G4bool SearchTimeMap(Reactant* molecule);
|
||||
int SearchUpperBoundTime(double time, bool sameTypeOfMolecule);
|
||||
|
||||
protected:
|
||||
G4MoleculeCounter();
|
||||
~G4MoleculeCounter() override;
|
||||
|
||||
CounterMapType fCounterMap;
|
||||
std::map<const G4MoleculeDefinition*, G4bool> fDontRegister;
|
||||
|
||||
G4int fVerbose;
|
||||
G4bool fCheckTimeIsConsistentWithScheduler;
|
||||
|
||||
struct Search
|
||||
const G4MolecularConfiguration* Molecule;
|
||||
G4MoleculeCounterIndex() : Molecule(nullptr) {}
|
||||
explicit G4MoleculeCounterIndex(const G4MolecularConfiguration* molecule) : Molecule(molecule)
|
||||
{}
|
||||
~G4MoleculeCounterIndex() override = default;
|
||||
G4bool operator<(G4VMoleculeCounterIndex const& other) const override
|
||||
{
|
||||
Search()
|
||||
{
|
||||
fLowerBoundSet = false;
|
||||
}
|
||||
CounterMapType::iterator fLastMoleculeSearched;
|
||||
NbMoleculeAgainstTime::iterator fLowerBoundTime;
|
||||
bool fLowerBoundSet;
|
||||
};
|
||||
return std::less{}(Molecule, static_cast<const G4MoleculeCounterIndex&>(other).Molecule);
|
||||
}
|
||||
G4bool operator==(G4VMoleculeCounterIndex const& other) const override
|
||||
{
|
||||
return std::equal_to{}(Molecule, static_cast<const G4MoleculeCounterIndex&>(other).Molecule);
|
||||
}
|
||||
G4String GetInfo() const override
|
||||
{
|
||||
G4String null = "null";
|
||||
if (Molecule == nullptr) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
G4String name = Molecule->GetName();
|
||||
G4String info = "Molecule: " + name;
|
||||
return info;
|
||||
}
|
||||
}
|
||||
const G4MolecularConfiguration* GetMolecule() const override { return Molecule; }
|
||||
};
|
||||
|
||||
std::unique_ptr<Search> fpLastSearch;
|
||||
class G4MoleculeCounter : public G4VUserMoleculeCounter<G4MoleculeCounterIndex>
|
||||
{
|
||||
//----------------------------------------------------------------------------
|
||||
public:
|
||||
G4MoleculeCounter();
|
||||
G4MoleculeCounter(G4String);
|
||||
~G4MoleculeCounter() override = default;
|
||||
|
||||
friend class G4Molecule;
|
||||
friend class G4VMoleculeCounter;
|
||||
};
|
||||
void InitializeUser() override;
|
||||
|
||||
public:
|
||||
std::unique_ptr<G4VMoleculeCounterIndex> BuildIndex(const G4Track*) const override;
|
||||
std::unique_ptr<G4VMoleculeCounterIndex> BuildIndex(const G4Track*,
|
||||
const G4StepPoint*) const override;
|
||||
std::unique_ptr<G4VMoleculeCounterIndex>
|
||||
BuildSimpleIndex(const G4MolecularConfiguration*) const override;
|
||||
};
|
||||
|
||||
+250
@@ -0,0 +1,250 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
|
||||
// Author: Christian Velten (2025)
|
||||
|
||||
#ifndef G4MOLECULECOUNTERMANAGER_HH
|
||||
#define G4MOLECULECOUNTERMANAGER_HH 1
|
||||
|
||||
#include "G4Exception.hh"
|
||||
#include "G4Threading.hh"
|
||||
#include "G4Types.hh"
|
||||
#include "G4VMoleculeCounter.hh"
|
||||
#include "G4VMoleculeReactionCounter.hh"
|
||||
#include "G4ios.hh"
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
class G4Event;
|
||||
class G4Run;
|
||||
class G4Step;
|
||||
class G4StepPoint;
|
||||
class G4Track;
|
||||
class G4MoleculeCounterManagerMessenger;
|
||||
|
||||
class G4MoleculeCounterManager final
|
||||
{
|
||||
private:
|
||||
struct Private
|
||||
{
|
||||
explicit Private() = default;
|
||||
};
|
||||
|
||||
public:
|
||||
G4MoleculeCounterManager(Private);
|
||||
~G4MoleculeCounterManager();
|
||||
|
||||
private:
|
||||
G4bool fInstancesRegistered{false};
|
||||
void RegisterInstance();
|
||||
|
||||
public:
|
||||
static G4MoleculeCounterManager* Instance();
|
||||
static G4MoleculeCounterManager* GetInstanceIfExists();
|
||||
static void DeleteInstance();
|
||||
|
||||
void Initialize();
|
||||
|
||||
//
|
||||
// Management
|
||||
|
||||
G4int RegisterCounter(std::unique_ptr<G4VMoleculeCounter>);
|
||||
G4int RegisterCounter(std::unique_ptr<G4VMoleculeReactionCounter>);
|
||||
void DeregisterAllCounters();
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
G4int RegisterCounter(std::map<G4int, T*>&, std::unique_ptr<T>, std::function<G4int()>);
|
||||
void InitializeMaster();
|
||||
void InitializeWorker();
|
||||
|
||||
public:
|
||||
// methods to receive forwarding from G4DNAChemistryManager
|
||||
void BeginOfEventAction(const G4Event*);
|
||||
void BeginOfRunAction(const G4Run*);
|
||||
void EndOfEventAction(const G4Event*);
|
||||
void EndOfRunAction(const G4Run*);
|
||||
// Dumping counters
|
||||
void DumpMasterCounters() const;
|
||||
void DumpWorkerCounters() const;
|
||||
// Accumulation of counters into master
|
||||
void AbsorbWorkerManagerCounters(const G4MoleculeCounterManager* = nullptr);
|
||||
|
||||
//
|
||||
// Calls to Molecule Counters
|
||||
public:
|
||||
// [[deprecated("This should only be used for IRT and may be replaced as well.")]]
|
||||
void AddMoleculeWithoutTrack(const G4MolecularConfiguration*, G4double, G4int = 1);
|
||||
// [[deprecated("This should only be used for IRT and may be replaced as well.")]]
|
||||
void RemoveMoleculeWithoutTrack(const G4MolecularConfiguration*, G4double, G4int = 1);
|
||||
|
||||
void AddMolecule(const G4Track*, G4double, G4int = 1);
|
||||
void RemoveMolecule(const G4Track*, G4double, G4int = 1);
|
||||
|
||||
void AddMolecule(const G4Track*, const G4StepPoint*, G4double, G4int = 1);
|
||||
void RemoveMolecule(const G4Track*, const G4StepPoint*, G4double, G4int = 1);
|
||||
|
||||
void ActivateCounterAtTimes(G4int, G4double, G4double, G4bool = true, G4bool = true);
|
||||
|
||||
//
|
||||
// Calls to Molecule Reaction Counters
|
||||
|
||||
// [[deprecated("TBD")]]
|
||||
void RecordReaction(const G4DNAMolecularReactionData*, G4double, G4int = 1);
|
||||
// void RecordReaction(const G4Track*, const G4Track*, const G4DNAMolecularReactionData*, G4double,
|
||||
// G4int = 1);
|
||||
|
||||
void ActivateReactionCounterAtTimes(G4int, G4double, G4double, G4bool = true, G4bool = true);
|
||||
|
||||
//
|
||||
// Other Calls to both types or only one (e.g., BroadcastIgnoreMolecule)
|
||||
|
||||
void ResetCounters();
|
||||
|
||||
void NotifyOfStep(const G4Step*);
|
||||
void NotifyOfFinalize();
|
||||
|
||||
// These will be broadcast to all counters registered at time of call
|
||||
void BroadcastIgnoreMolecule(const G4MoleculeDefinition*);
|
||||
void BroadcastIgnoreReactant(const G4MolecularConfiguration*);
|
||||
void BroadcastRegisterAllMoleculesAndReactants();
|
||||
|
||||
private:
|
||||
static const G4MoleculeCounterManager* fpMasterInstance;
|
||||
static std::vector<const G4MoleculeCounterManager*> fWorkerInstances;
|
||||
G4ThreadLocalStatic std::unique_ptr<G4MoleculeCounterManager> fpInstance;
|
||||
|
||||
std::unique_ptr<G4MoleculeCounterManagerMessenger> fpMessenger;
|
||||
|
||||
G4int fVerbosity;
|
||||
G4bool fIsInitialized;
|
||||
G4bool fIsActive;
|
||||
static std::atomic<G4bool> fResetCountersBeforeEvent;
|
||||
static std::atomic<G4bool> fResetCountersBeforeRun;
|
||||
static std::atomic<G4bool> fResetMasterCounterWithWorkers;
|
||||
static std::atomic<G4bool> fAccumulateCounterIntoMaster;
|
||||
|
||||
std::map<G4int, G4VMoleculeCounter*> fCounters{};
|
||||
std::map<G4int, G4VMoleculeReactionCounter*> fReactionCounters{};
|
||||
|
||||
public:
|
||||
G4bool GetIsActive() const { return fIsActive; }
|
||||
void SetIsActive(G4bool flag) { fIsActive = flag; }
|
||||
|
||||
G4int GetVerbosity() const { return fVerbosity; }
|
||||
void SetVerbosity(G4int v) { fVerbosity = v; }
|
||||
|
||||
G4bool GetResetCountersBeforeEvent() const;
|
||||
void SetResetCountersBeforeEvent(G4bool = true);
|
||||
|
||||
G4bool GetResetCountersBeforeRun() const;
|
||||
void SetResetCountersBeforeRun(G4bool = true);
|
||||
|
||||
G4bool GetResetMasterCounterWithWorkers() const;
|
||||
void SetResetMasterCounterWithWorkers(G4bool = true);
|
||||
|
||||
G4bool GetAccumulateCounterIntoMaster() const;
|
||||
void SetAccumulateCounterIntoMaster(G4bool = true);
|
||||
|
||||
std::vector<const G4VMoleculeCounter*> GetMoleculeCounters() const;
|
||||
std::vector<const G4VMoleculeCounter*> GetMoleculeCounters(G4String) const;
|
||||
template<typename T = G4VMoleculeCounter>
|
||||
const T* GetMoleculeCounter(G4int) const;
|
||||
G4VMoleculeCounter* GetEditableMoleculeCounter(G4int) const;
|
||||
|
||||
std::vector<const G4VMoleculeReactionCounter*> GetMoleculeReactionCounters() const;
|
||||
std::vector<const G4VMoleculeReactionCounter*> GetMoleculeReactionCounters(G4String) const;
|
||||
G4VMoleculeReactionCounter* GetEditableMoleculeReactionCounter(G4int) const;
|
||||
template<typename T = G4VMoleculeReactionCounter>
|
||||
const T* GetMoleculeReactionCounter(G4int) const;
|
||||
|
||||
private:
|
||||
G4ThreadLocalStatic std::atomic<G4bool> fBeginOfEventTriggered;
|
||||
static std::atomic<G4bool> fBeginOfRunTriggered;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
G4int G4MoleculeCounterManager::RegisterCounter(std::map<G4int, T*>& map,
|
||||
std::unique_ptr<T> counter,
|
||||
std::function<G4int()> idProvider)
|
||||
{
|
||||
// this template allows for more than one counter type to be registered in the same way without
|
||||
// duplicating code; see public methods for G4VMoleculeCounter and G4VMoleculeReactionCounter
|
||||
|
||||
if (fVerbosity > 0) {
|
||||
G4cout << "G4MoleculeCounterManager::RegisterCounter ("
|
||||
<< (G4Threading::IsMasterThread() ? "master" : "worker") << ")" << G4endl;
|
||||
}
|
||||
|
||||
if (counter->GetManagedId() >= 0) {
|
||||
G4ExceptionDescription description;
|
||||
description << "Trying to add a counter whose id was already altered to be non-negative!\n";
|
||||
description << " Id: " << counter->GetManagedId() << "\n";
|
||||
description << "Name: " << counter->GetName();
|
||||
G4Exception("G4MoleculeCounterManager::RegisterCounter", "MOLMAN002", FatalErrorInArgument,
|
||||
description);
|
||||
}
|
||||
|
||||
T* sp = counter.release();
|
||||
// Set managed Id
|
||||
sp->SetManagedId(idProvider());
|
||||
|
||||
map.emplace(sp->GetManagedId(), sp);
|
||||
|
||||
return sp->GetManagedId();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
const T* G4MoleculeCounterManager::GetMoleculeCounter(G4int id) const
|
||||
{
|
||||
static_assert(std::is_base_of<G4VMoleculeCounter, T>::value,
|
||||
"T must be derived from G4VMoleculeCounter!");
|
||||
auto base_ptr = GetEditableMoleculeCounter(id);
|
||||
if (base_ptr == nullptr) return nullptr;
|
||||
const T* ptr = dynamic_cast<const T*>(base_ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T* G4MoleculeCounterManager::GetMoleculeReactionCounter(G4int id) const
|
||||
{
|
||||
static_assert(std::is_base_of<G4VMoleculeReactionCounter, T>::value,
|
||||
"T must be derived from G4VMoleculeReactionCounter!");
|
||||
auto base_ptr = GetEditableMoleculeReactionCounter(id);
|
||||
if (base_ptr == nullptr) return nullptr;
|
||||
const T* ptr = dynamic_cast<const T*>(base_ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#endif // G4MOLECULECOUNTERMANAGER_HH
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// Author: Christian Velten (2025)
|
||||
|
||||
#ifndef G4MOLECULECOUNTERMANAGERMESSENGER_HH
|
||||
#define G4MOLECULECOUNTERMANAGERMESSENGER_HH 1
|
||||
|
||||
#include "G4UIcmdWithABool.hh"
|
||||
#include "G4UIcmdWithAnInteger.hh"
|
||||
#include "G4UIdirectory.hh"
|
||||
#include "G4UImessenger.hh"
|
||||
|
||||
#include <memory>
|
||||
|
||||
class G4MoleculeCounterManager;
|
||||
|
||||
class G4MoleculeCounterManagerMessenger : public G4UImessenger
|
||||
{
|
||||
public:
|
||||
explicit G4MoleculeCounterManagerMessenger(G4MoleculeCounterManager*);
|
||||
~G4MoleculeCounterManagerMessenger() override = default;
|
||||
void SetNewValue(G4UIcommand*, G4String) override;
|
||||
|
||||
private:
|
||||
void InitializeCommands();
|
||||
|
||||
private:
|
||||
G4MoleculeCounterManager* fpManager{nullptr};
|
||||
std::unique_ptr<G4UIdirectory> fpManagerDir;
|
||||
std::unique_ptr<G4UIcmdWithABool> fpActiveCmd;
|
||||
std::unique_ptr<G4UIcmdWithABool> fpResetBeforeEventCmd;
|
||||
std::unique_ptr<G4UIcmdWithABool> fpResetBeforeRunCmd;
|
||||
std::unique_ptr<G4UIcmdWithABool> fpAccumulateIntoMasterCmd;
|
||||
std::unique_ptr<G4UIcmdWithAnInteger> fpVerboseCmd;
|
||||
};
|
||||
|
||||
#endif // G4MOLECULECOUNTERMANAGERMESSENGER_HH
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// Author: Christian Velten (2025)
|
||||
|
||||
#ifndef G4MOLECULECOUNTERTEMPLATES_HH
|
||||
#define G4MOLECULECOUNTERTEMPLATES_HH 1
|
||||
|
||||
#include "G4Types.hh"
|
||||
#include "G4VMoleculeCounter.hh"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace G4
|
||||
{
|
||||
namespace MoleculeCounter
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
G4String GetTemplateTypeName()
|
||||
{
|
||||
return G4String(typeid(T).name());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
G4bool Contains(const std::set<T>& _set, const T& _value)
|
||||
{
|
||||
return std::binary_search(_set.cbegin(), _set.cend(), _value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
G4bool Contains(const std::vector<T>& _vector, const T& _value)
|
||||
{
|
||||
auto p = std::find(_vector.cbegin(), _vector.cend(), _value);
|
||||
return p != _vector.cend();
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
G4bool ContainsKey(const std::map<T, U>& _map, const T& _key)
|
||||
{
|
||||
auto keys = GetMapIndices(_map);
|
||||
return Contains(keys, _key);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename T, typename U>
|
||||
const std::vector<T> GetMapIndices(const std::map<T, U>& _map)
|
||||
{
|
||||
std::vector<T> output;
|
||||
for (auto const& it : _map)
|
||||
output.push_back(it.first);
|
||||
return output;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
void DumpCounterMapIndices(const std::map<T, InnerCounterMapType>& map, G4bool includeEmpty = false)
|
||||
{
|
||||
G4cout << "--- BEGIN COUNTER MAP INDEX DUMP ---" << G4endl;
|
||||
auto i = 0;
|
||||
for (auto const& it : map) {
|
||||
if (!includeEmpty && it.second.size() == 0) continue;
|
||||
G4cout << i++ << ": " << it.first.GetInfo() << G4endl;
|
||||
}
|
||||
G4cout << "--- END COUNTER MAP INDEX DUMP ---" << G4endl;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
void DumpCounterMapContents(const std::map<T, InnerCounterMapType>& map,
|
||||
G4bool includeEmpty = false)
|
||||
{
|
||||
G4cout << "--- BEGIN COUNTER MAP DUMP ---" << G4endl;
|
||||
for (auto const& it : map) {
|
||||
if (!includeEmpty && it.second.size() == 0) continue;
|
||||
G4cout << " :: " << it.first.GetInfo() << G4endl;
|
||||
for (auto const& it2 : it.second) {
|
||||
G4cout << std::setw(3) << std::setprecision(3) << " " << G4BestUnit(it2.first, "Time")
|
||||
<< " " << std::setw(5) << it2.second << G4endl;
|
||||
}
|
||||
}
|
||||
G4cout << "--- END COUNTER MAP DUMP ---" << G4endl;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
std::set<G4double> GetRecordedTimes(const std::map<T, InnerCounterMapType>& map)
|
||||
{
|
||||
std::set<G4double> output{};
|
||||
for (const auto& it : map) {
|
||||
G4cerr << it.second.size() << G4endl;
|
||||
for (const auto& it2 : it.second) {
|
||||
output.insert(it2.first);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename TKey, typename TValue, typename TComp>
|
||||
typename std::map<TKey, TValue, TComp>::iterator
|
||||
FindClosestEntryForKey(std::map<TKey, TValue, TComp>& map, TKey key)
|
||||
{
|
||||
if (map.empty()) return map.end();
|
||||
|
||||
auto it_lb = map.lower_bound(key);
|
||||
|
||||
if (it_lb == map.begin()) return it_lb;
|
||||
if (it_lb == map.end()) return --it_lb;
|
||||
|
||||
auto prev_it = std::prev(it_lb);
|
||||
|
||||
if (std::abs(it_lb->first - key) < std::abs(prev_it->first - key))
|
||||
return it_lb;
|
||||
else
|
||||
return prev_it;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // namespace MoleculeCounter
|
||||
} // namespace G4
|
||||
|
||||
#endif
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
#ifndef G4MOLECULECOUNTERTIMECOMPARER_HH
|
||||
#define G4MOLECULECOUNTERTIMECOMPARER_HH 1
|
||||
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4Types.hh"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
class G4MoleculeCounterTimeComparer
|
||||
{
|
||||
public:
|
||||
enum TimeComparerType
|
||||
{
|
||||
FixedPrecision,
|
||||
VariablePrecision
|
||||
};
|
||||
|
||||
public:
|
||||
G4MoleculeCounterTimeComparer();
|
||||
virtual ~G4MoleculeCounterTimeComparer() = default;
|
||||
|
||||
G4MoleculeCounterTimeComparer(const G4MoleculeCounterTimeComparer&);
|
||||
G4MoleculeCounterTimeComparer& operator=(const G4MoleculeCounterTimeComparer&);
|
||||
|
||||
void SetFixedPrecision(G4double);
|
||||
void SetVariablePrecision(const std::vector<G4double>&, const std::vector<G4double>&);
|
||||
void SetVariablePrecision(const std::map<G4double, G4double>&);
|
||||
|
||||
G4double GetPrecisionAtTime(G4double) const;
|
||||
|
||||
bool operator()(const G4double&, const G4double&) const;
|
||||
|
||||
private:
|
||||
TimeComparerType fType;
|
||||
G4double fPrecision{1 * picosecond};
|
||||
std::map<G4double, G4double> fVariablePrecision{};
|
||||
|
||||
public: // Factory
|
||||
static G4MoleculeCounterTimeComparer CreateWithFixedPrecision(G4double);
|
||||
static G4MoleculeCounterTimeComparer CreateWithVariablePrecision(const std::map<G4double, G4double>&);
|
||||
};
|
||||
|
||||
#endif
|
||||
-1
@@ -32,7 +32,6 @@
|
||||
#include <memory>
|
||||
|
||||
class G4UIcmdWithAString;
|
||||
class G4DNAMolecularReactionTable;
|
||||
class G4UIcmdWithoutParameter;
|
||||
class G4UIcmdWithADoubleAndUnit;
|
||||
class G4UIcmdWithAnInteger;
|
||||
|
||||
+117
-64
@@ -27,80 +27,133 @@
|
||||
// Geant4
|
||||
//
|
||||
// Created by Mathieu Karamitros on 02/11/2016.
|
||||
// Modified by Christian Velten on 10/27/2024.
|
||||
//
|
||||
//
|
||||
#ifndef G4VMOLECULECOUNTER_HH
|
||||
#define G4VMOLECULECOUNTER_HH 1
|
||||
|
||||
#pragma once
|
||||
#include "G4MoleculeCounterTimeComparer.hh"
|
||||
#include "G4VMoleculeCounterInternalBase.hh"
|
||||
|
||||
#include <G4Types.hh>
|
||||
#include <G4ios.hh>
|
||||
#include "G4ThreeVector.hh"
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
class G4MolecularConfiguration;
|
||||
|
||||
class G4MoleculeDefinition;
|
||||
class G4Track;
|
||||
class G4StepPoint;
|
||||
|
||||
class G4VMoleculeCounter
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class G4VMoleculeCounter : public G4VMoleculeCounterInternalBase
|
||||
{
|
||||
protected:
|
||||
static G4ThreadLocal G4VMoleculeCounter* fpInstance;
|
||||
G4bool fUse = false;
|
||||
template<typename>
|
||||
friend class G4VUserMoleculeCounter;
|
||||
|
||||
G4VMoleculeCounter() = default;
|
||||
|
||||
virtual ~G4VMoleculeCounter() = default;
|
||||
|
||||
public:
|
||||
static void SetInstance(G4VMoleculeCounter*);
|
||||
|
||||
static void DeleteInstance();
|
||||
|
||||
using Reactant = const G4MolecularConfiguration;
|
||||
|
||||
/*
|
||||
* If no instance of G4VMoleculeCounter is provided
|
||||
* then use G4MoleculeCounter
|
||||
*/
|
||||
static G4VMoleculeCounter* Instance();
|
||||
|
||||
static void InitializeInstance();
|
||||
|
||||
/*
|
||||
* If the molecule counter is used, it will be called
|
||||
* at every creation/deletion of a molecule to
|
||||
* to increase/decrease the number at a given time.
|
||||
*/
|
||||
void Use(G4bool flag = true);
|
||||
|
||||
G4bool InUse();
|
||||
|
||||
//----------------------------------------------------
|
||||
|
||||
virtual void Initialize() = 0;
|
||||
|
||||
virtual void ResetCounter() = 0;
|
||||
|
||||
virtual void AddAMoleculeAtTime(Reactant*,
|
||||
G4double time,
|
||||
const G4ThreeVector* position = nullptr,
|
||||
int number = 1) = 0;
|
||||
|
||||
virtual void RemoveAMoleculeAtTime(Reactant*,
|
||||
G4double time,
|
||||
const G4ThreeVector* position = nullptr,
|
||||
int number = 1) = 0;
|
||||
|
||||
/* The dynamics of the given molecule won't be recorded. */
|
||||
virtual void DontRegister(const G4MoleculeDefinition*)
|
||||
public:
|
||||
enum MoleculeCounterType
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool IsRegistered(const G4MoleculeDefinition*)
|
||||
Other,
|
||||
Basic,
|
||||
Mesoscopic,
|
||||
};
|
||||
struct G4VMoleculeCounterIndex : public G4VMoleculeCounterIndexInterface
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual ~G4VMoleculeCounterIndex() = default;
|
||||
virtual G4bool operator<(G4VMoleculeCounterIndex const&) const = 0;
|
||||
virtual G4bool operator==(G4VMoleculeCounterIndex const&) const = 0;
|
||||
virtual G4String GetInfo() const = 0;
|
||||
virtual const G4MolecularConfiguration* GetMolecule() const = 0;
|
||||
};
|
||||
|
||||
virtual void RegisterAll()
|
||||
{
|
||||
}
|
||||
};
|
||||
private:
|
||||
G4VMoleculeCounter();
|
||||
G4VMoleculeCounter(const G4String&, MoleculeCounterType = MoleculeCounterType::Other);
|
||||
G4VMoleculeCounter(G4VMoleculeCounter const&) = delete;
|
||||
void operator=(G4VMoleculeCounter const& x) = delete;
|
||||
|
||||
public:
|
||||
~G4VMoleculeCounter() override = default;
|
||||
|
||||
public:
|
||||
virtual std::unique_ptr<G4VMoleculeCounterIndex> BuildIndex(const G4Track*) const = 0;
|
||||
virtual std::unique_ptr<G4VMoleculeCounterIndex> BuildIndex(const G4Track*,
|
||||
const G4StepPoint*) const = 0;
|
||||
virtual std::unique_ptr<G4VMoleculeCounterIndex> BuildSimpleIndex(const G4MolecularConfiguration*) const = 0;
|
||||
|
||||
virtual void AddMolecule(std::unique_ptr<G4VMoleculeCounterIndex>, G4double, G4int = 1) = 0;
|
||||
virtual void RemoveMolecule(std::unique_ptr<G4VMoleculeCounterIndex>, G4double, G4int = 1) = 0;
|
||||
|
||||
virtual std::set<const G4MolecularConfiguration*> GetRecordedMolecules() const = 0;
|
||||
std::set<G4double> GetRecordedTimes() const override = 0;
|
||||
|
||||
virtual void SchedulerFinalizedTracking() = 0;
|
||||
|
||||
protected:
|
||||
MoleculeCounterType fType{MoleculeCounterType::Other};
|
||||
|
||||
G4bool fSensitiveToStepping{false};
|
||||
G4bool fNegativeCountsAreFatal{true};
|
||||
|
||||
std::set<const G4MoleculeDefinition*> fIgnoredMolecules{};
|
||||
std::set<const G4MolecularConfiguration*> fIgnoredReactants{};
|
||||
|
||||
public:
|
||||
MoleculeCounterType GetType() const;
|
||||
|
||||
G4bool GetSensitiveToStepping() const;
|
||||
void SetSensitiveToStepping(G4bool = true);
|
||||
|
||||
G4bool GetNegativeCountsAreFatal() const;
|
||||
|
||||
// Ignore certain molecules from counting
|
||||
void IgnoreMolecule(const G4MoleculeDefinition*);
|
||||
void IgnoreReactant(const G4MolecularConfiguration*);
|
||||
void RegisterAll();
|
||||
|
||||
G4bool IsReactantIgnored(const G4MoleculeDefinition*) const;
|
||||
G4bool IsReactantIgnored(const G4MolecularConfiguration*) const;
|
||||
|
||||
protected:
|
||||
void SetNegativeCountsAreFatal(G4bool);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline G4VMoleculeCounter::MoleculeCounterType G4VMoleculeCounter::GetType() const
|
||||
{
|
||||
return fType;
|
||||
}
|
||||
|
||||
inline G4bool G4VMoleculeCounter::GetSensitiveToStepping() const
|
||||
{
|
||||
return fSensitiveToStepping;
|
||||
}
|
||||
|
||||
inline G4bool G4VMoleculeCounter::GetNegativeCountsAreFatal() const
|
||||
{
|
||||
return fNegativeCountsAreFatal;
|
||||
}
|
||||
inline void G4VMoleculeCounter::SetNegativeCountsAreFatal(G4bool flag)
|
||||
{
|
||||
fNegativeCountsAreFatal = flag;
|
||||
}
|
||||
|
||||
inline void G4VMoleculeCounter::IgnoreMolecule(const G4MoleculeDefinition* molecule)
|
||||
{
|
||||
fIgnoredMolecules.insert(molecule);
|
||||
}
|
||||
|
||||
inline void G4VMoleculeCounter::IgnoreReactant(const G4MolecularConfiguration* reactant)
|
||||
{
|
||||
fIgnoredReactants.insert(reactant);
|
||||
}
|
||||
|
||||
inline void G4VMoleculeCounter::RegisterAll()
|
||||
{
|
||||
fIgnoredMolecules.clear();
|
||||
fIgnoredReactants.clear();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+264
@@ -0,0 +1,264 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// Author: Christian Velten (2025)
|
||||
|
||||
#ifndef G4VMoleculeCounterInternalBaseBASE_HH
|
||||
#define G4VMoleculeCounterInternalBaseBASE_HH 1
|
||||
|
||||
#include "G4Exception.hh"
|
||||
#include "G4MoleculeCounterTimeComparer.hh"
|
||||
#include "G4String.hh"
|
||||
#include "G4Types.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
#include "G4ios.hh"
|
||||
|
||||
#include <iomanip>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
namespace G4
|
||||
{
|
||||
namespace MoleculeCounter
|
||||
{
|
||||
struct FixedTimeComparer
|
||||
{
|
||||
G4bool operator()(const G4double& a, const G4double& b) const;
|
||||
static G4ThreadLocal G4double fPrecision;
|
||||
};
|
||||
} // namespace MoleculeCounter
|
||||
} // namespace G4
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using InnerCounterMapType = std::map<G4double, G4int, G4MoleculeCounterTimeComparer>;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class G4VMoleculeCounterInternalBase
|
||||
{
|
||||
friend class G4VMoleculeCounter;
|
||||
friend class G4VMoleculeReactionCounter;
|
||||
// only allow these classes to derive
|
||||
|
||||
public:
|
||||
struct G4VMoleculeCounterIndexInterface
|
||||
{
|
||||
virtual ~G4VMoleculeCounterIndexInterface() = default;
|
||||
virtual G4String GetInfo() const = 0;
|
||||
};
|
||||
|
||||
private:
|
||||
G4VMoleculeCounterInternalBase();
|
||||
G4VMoleculeCounterInternalBase(const G4String&);
|
||||
G4VMoleculeCounterInternalBase(G4VMoleculeCounterInternalBase const&) = delete;
|
||||
void operator=(G4VMoleculeCounterInternalBase const& x) = delete;
|
||||
|
||||
public:
|
||||
virtual ~G4VMoleculeCounterInternalBase() = default;
|
||||
|
||||
public:
|
||||
virtual void Initialize() = 0;
|
||||
virtual void InitializeUser() = 0;
|
||||
virtual void ResetCounter() = 0;
|
||||
virtual void Dump() const = 0;
|
||||
virtual void DumpCounterMapIndices() const = 0;
|
||||
|
||||
virtual std::set<G4double> GetRecordedTimes() const = 0;
|
||||
|
||||
virtual void AbsorbCounter(const G4VMoleculeCounterInternalBase*) = 0;
|
||||
|
||||
private:
|
||||
static G4ThreadLocal G4int _createdCounters;
|
||||
|
||||
protected:
|
||||
G4bool fIsInitialized{false};
|
||||
|
||||
G4int fId;
|
||||
G4int fManagedId{-1};
|
||||
G4String fName{};
|
||||
|
||||
G4int fVerbose{0};
|
||||
|
||||
G4double fActiveLowerBound{0}, fActiveUpperBound{std::numeric_limits<G4double>::max()};
|
||||
G4bool fActiveLowerBoundInclusive{true}, fActiveUpperBoundInclusive{true};
|
||||
|
||||
G4bool fCheckTimeIsConsistentWithScheduler{true};
|
||||
G4bool fCheckRecordedTimesAreConsistent{true};
|
||||
|
||||
G4MoleculeCounterTimeComparer fTimeComparer{};
|
||||
|
||||
public:
|
||||
G4int GetId() const;
|
||||
void SetManagedId(G4int);
|
||||
G4int GetManagedId() const;
|
||||
const G4String& GetName() const;
|
||||
|
||||
G4int GetVerbose() const;
|
||||
void SetVerbose(G4int);
|
||||
|
||||
// Set counter active w.r.t. time
|
||||
G4double GetActiveLowerBound() const;
|
||||
void SetActiveLowerBound(G4double, G4bool = true);
|
||||
G4double GetActiveUpperBound() const;
|
||||
void SetActiveUpperBound(G4double, G4bool = true);
|
||||
G4bool GetActiveLowerBoundInclusive() const;
|
||||
G4bool GetActiveUpperBoundInclusive() const;
|
||||
G4bool IsTimeBelowLowerBound(G4double) const;
|
||||
G4bool IsTimeAboveUpperBound(G4double) const;
|
||||
G4bool IsActiveAtGlobalTime(G4double) const;
|
||||
|
||||
G4bool GetCheckTimeConsistencyWithScheduler() const; // w.r.t. scheduler time
|
||||
void SetCheckTimeConsistencyWithScheduler(G4bool = true);
|
||||
G4bool GetCheckRecordedTimeConsistency() const; // w.r.t last recorded time
|
||||
void SetCheckRecordedTimeConsistency(G4bool = true);
|
||||
|
||||
const G4MoleculeCounterTimeComparer& GetTimeComparer() const;
|
||||
void SetTimeComparer(const G4MoleculeCounterTimeComparer&);
|
||||
|
||||
public:
|
||||
static void SetFixedTimePrecision(G4double);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline G4int G4VMoleculeCounterInternalBase::GetId() const
|
||||
{
|
||||
return fId;
|
||||
}
|
||||
|
||||
inline void G4VMoleculeCounterInternalBase::SetManagedId(G4int id)
|
||||
{
|
||||
if (fManagedId > -1) {
|
||||
G4ExceptionDescription description;
|
||||
description << "Someone is trying to change the managed id of this counter but it was already "
|
||||
"changed from -1!\n";
|
||||
description << " Id: " << fManagedId << "\n";
|
||||
description << "Name: " << fName << "\n";
|
||||
G4Exception("G4VMoleculeCounterInternalBase::SetManagedId", "MOLCTR000", FatalException, description);
|
||||
}
|
||||
fManagedId = id;
|
||||
}
|
||||
inline G4int G4VMoleculeCounterInternalBase::GetManagedId() const
|
||||
{
|
||||
return fManagedId;
|
||||
}
|
||||
|
||||
inline const G4String& G4VMoleculeCounterInternalBase::GetName() const
|
||||
{
|
||||
return fName;
|
||||
}
|
||||
|
||||
inline G4int G4VMoleculeCounterInternalBase::GetVerbose() const
|
||||
{
|
||||
return fVerbose;
|
||||
}
|
||||
inline void G4VMoleculeCounterInternalBase::SetVerbose(G4int verbose)
|
||||
{
|
||||
fVerbose = verbose;
|
||||
}
|
||||
|
||||
inline G4double G4VMoleculeCounterInternalBase::GetActiveLowerBound() const
|
||||
{
|
||||
return fActiveLowerBound;
|
||||
}
|
||||
inline void G4VMoleculeCounterInternalBase::SetActiveLowerBound(G4double time, G4bool inclusive)
|
||||
{
|
||||
fActiveLowerBound = time;
|
||||
fActiveLowerBoundInclusive = inclusive;
|
||||
}
|
||||
|
||||
inline G4double G4VMoleculeCounterInternalBase::GetActiveUpperBound() const
|
||||
{
|
||||
return fActiveUpperBound;
|
||||
}
|
||||
inline void G4VMoleculeCounterInternalBase::SetActiveUpperBound(G4double time, G4bool inclusive)
|
||||
{
|
||||
fActiveUpperBound = time;
|
||||
fActiveUpperBoundInclusive = inclusive;
|
||||
}
|
||||
|
||||
inline G4bool G4VMoleculeCounterInternalBase::GetActiveLowerBoundInclusive() const
|
||||
{
|
||||
return fActiveLowerBoundInclusive;
|
||||
}
|
||||
inline G4bool G4VMoleculeCounterInternalBase::GetActiveUpperBoundInclusive() const
|
||||
{
|
||||
return fActiveUpperBoundInclusive;
|
||||
}
|
||||
|
||||
inline G4bool G4VMoleculeCounterInternalBase::IsTimeBelowLowerBound(G4double time) const
|
||||
{
|
||||
return (fActiveLowerBoundInclusive && time < fActiveLowerBound)
|
||||
|| (!fActiveLowerBoundInclusive && time <= fActiveLowerBound);
|
||||
}
|
||||
inline G4bool G4VMoleculeCounterInternalBase::IsTimeAboveUpperBound(G4double time) const
|
||||
{
|
||||
return (fActiveUpperBoundInclusive && time > fActiveUpperBound)
|
||||
|| (!fActiveUpperBoundInclusive && time >= fActiveUpperBound);
|
||||
}
|
||||
inline G4bool G4VMoleculeCounterInternalBase::IsActiveAtGlobalTime(G4double time) const
|
||||
{
|
||||
return !(IsTimeBelowLowerBound(time) || IsTimeAboveUpperBound(time));
|
||||
}
|
||||
|
||||
inline G4bool G4VMoleculeCounterInternalBase::GetCheckTimeConsistencyWithScheduler() const
|
||||
{
|
||||
return fCheckTimeIsConsistentWithScheduler;
|
||||
}
|
||||
inline void G4VMoleculeCounterInternalBase::SetCheckTimeConsistencyWithScheduler(G4bool flag)
|
||||
{
|
||||
fCheckTimeIsConsistentWithScheduler = flag;
|
||||
}
|
||||
|
||||
inline G4bool G4VMoleculeCounterInternalBase::GetCheckRecordedTimeConsistency() const
|
||||
{
|
||||
return fCheckRecordedTimesAreConsistent;
|
||||
}
|
||||
inline void G4VMoleculeCounterInternalBase::SetCheckRecordedTimeConsistency(G4bool flag)
|
||||
{
|
||||
fCheckRecordedTimesAreConsistent = flag;
|
||||
}
|
||||
|
||||
inline const G4MoleculeCounterTimeComparer& G4VMoleculeCounterInternalBase::GetTimeComparer() const
|
||||
{
|
||||
return fTimeComparer;
|
||||
}
|
||||
|
||||
inline void G4VMoleculeCounterInternalBase::SetTimeComparer(const G4MoleculeCounterTimeComparer& comparer)
|
||||
{
|
||||
if (fIsInitialized) {
|
||||
G4Exception("G4VMoleculeCounterInternalBase::SetTimeComparer()", "AlreadyInitialized", JustWarning,
|
||||
"Molecule counter was already initialized, assigning the time comparer now may "
|
||||
"have no effect!");
|
||||
}
|
||||
fTimeComparer = comparer;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#endif
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// Author: Christian Velten (2025)
|
||||
#ifndef G4VMOLECULEREACTIONCOUNTER_HH
|
||||
#define G4VMOLECULEREACTIONCOUNTER_HH 1
|
||||
|
||||
#include "G4VMoleculeCounterInternalBase.hh"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
class G4Track;
|
||||
class G4DNAMolecularReactionData;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class G4VMoleculeReactionCounter : public G4VMoleculeCounterInternalBase
|
||||
{
|
||||
template<typename>
|
||||
friend class G4VUserMoleculeReactionCounter;
|
||||
|
||||
public:
|
||||
enum MoleculeReactionCounterType
|
||||
{
|
||||
Other,
|
||||
Basic,
|
||||
};
|
||||
struct G4VMoleculeReactionCounterIndex
|
||||
{
|
||||
virtual ~G4VMoleculeReactionCounterIndex() = default;
|
||||
virtual G4bool operator<(G4VMoleculeReactionCounterIndex const&) const = 0;
|
||||
virtual G4bool operator==(G4VMoleculeReactionCounterIndex const&) const = 0;
|
||||
virtual G4String GetInfo() const = 0;
|
||||
virtual const G4DNAMolecularReactionData* GetReactionData() const = 0;
|
||||
};
|
||||
|
||||
private:
|
||||
G4VMoleculeReactionCounter();
|
||||
G4VMoleculeReactionCounter(const G4String&, MoleculeReactionCounterType =
|
||||
MoleculeReactionCounterType::Basic);
|
||||
G4VMoleculeReactionCounter(G4VMoleculeReactionCounter const&) = delete;
|
||||
void operator=(G4VMoleculeReactionCounter const& x) = delete;
|
||||
|
||||
public:
|
||||
~G4VMoleculeReactionCounter() override = default;
|
||||
|
||||
public:
|
||||
// virtual std::unique_ptr<G4VMoleculeReactionCounterIndex> BuildIndex(const G4Track*, const G4Track*, const G4DNAMolecularReactionData*) const = 0;
|
||||
virtual std::unique_ptr<G4VMoleculeReactionCounterIndex> BuildSimpleIndex(const G4DNAMolecularReactionData*) const = 0;
|
||||
|
||||
virtual void RecordReaction(std::unique_ptr<G4VMoleculeReactionCounterIndex>, G4double, G4int = 1) = 0;
|
||||
|
||||
virtual std::set<const G4DNAMolecularReactionData*> GetRecordedReactions() const = 0;
|
||||
|
||||
protected:
|
||||
MoleculeReactionCounterType fType{MoleculeReactionCounterType::Basic};
|
||||
|
||||
public:
|
||||
MoleculeReactionCounterType GetType() const;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline G4VMoleculeReactionCounter::MoleculeReactionCounterType G4VMoleculeReactionCounter::GetType() const
|
||||
{
|
||||
return fType;
|
||||
}
|
||||
|
||||
#endif
|
||||
+764
@@ -0,0 +1,764 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// Author: Christian Velten (2025)
|
||||
|
||||
#ifndef G4VUSERMOLECULECOUNTER_HH
|
||||
#define G4VUSERMOLECULECOUNTER_HH 1
|
||||
|
||||
#include "G4MoleculeCounterManager.hh"
|
||||
#include "G4MolecularConfiguration.hh"
|
||||
#include "G4MoleculeCounterTemplates.hh"
|
||||
#include "G4Scheduler.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
#include "G4VMoleculeCounter.hh"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class TIndex>
|
||||
class G4VUserMoleculeCounter : public G4VMoleculeCounter
|
||||
{
|
||||
static_assert(std::is_base_of<G4VMoleculeCounter::G4VMoleculeCounterIndex, TIndex>::value,
|
||||
"TIndex must be derived from G4VMoleculeCounter::G4VMoleculeCounterIndex! "
|
||||
"No forward declaration is allowed.");
|
||||
|
||||
protected:
|
||||
struct Search;
|
||||
|
||||
public:
|
||||
G4VUserMoleculeCounter();
|
||||
G4VUserMoleculeCounter(G4String, MoleculeCounterType = MoleculeCounterType::Other);
|
||||
~G4VUserMoleculeCounter() override = default;
|
||||
|
||||
public:
|
||||
void Initialize() final;
|
||||
void InitializeUser() override = 0;
|
||||
void ResetCounter() override;
|
||||
void Dump() const override;
|
||||
void DumpCounterMapIndices() const override;
|
||||
|
||||
void AbsorbCounter(const G4VMoleculeCounterInternalBase*) override;
|
||||
|
||||
std::unique_ptr<G4VMoleculeCounter::G4VMoleculeCounterIndex> BuildIndex(const G4Track*) const override = 0;
|
||||
std::unique_ptr<G4VMoleculeCounter::G4VMoleculeCounterIndex> BuildIndex(const G4Track*, const G4StepPoint*) const override = 0;
|
||||
std::unique_ptr<G4VMoleculeCounter::G4VMoleculeCounterIndex> BuildSimpleIndex(const G4MolecularConfiguration*) const override = 0;
|
||||
|
||||
void AddMolecule(std::unique_ptr<G4VMoleculeCounter::G4VMoleculeCounterIndex>, G4double, G4int = 1) override;
|
||||
void RemoveMolecule(std::unique_ptr<G4VMoleculeCounter::G4VMoleculeCounterIndex>, G4double, G4int = 1) override;
|
||||
|
||||
std::set<const G4MolecularConfiguration*> GetRecordedMolecules() const override;
|
||||
std::set<G4double> GetRecordedTimes() const override;
|
||||
|
||||
void SchedulerFinalizedTracking() override;
|
||||
|
||||
protected:
|
||||
std::map<TIndex, InnerCounterMapType> fCounterMap{};
|
||||
std::map<TIndex, G4int> fShadowCounterMap{};
|
||||
|
||||
public:
|
||||
const std::map<TIndex, InnerCounterMapType>& GetCounterMap() const { return fCounterMap; }
|
||||
std::vector<TIndex> GetMapIndices() const;
|
||||
|
||||
virtual G4int GetNbMoleculesAtTime(const TIndex&, G4double) const;
|
||||
virtual G4int GetNbMoleculesAtTime(Search&, const TIndex&, G4double) const;
|
||||
virtual std::vector<G4int> GetNbMoleculesAtTimes(const TIndex&, const std::vector<G4double>&) const;
|
||||
|
||||
//-SEARCH-----------------------------------------------------------------------
|
||||
protected:
|
||||
struct Search
|
||||
{
|
||||
Search() : fLowerBoundSet(false) {}
|
||||
typename std::map<TIndex, InnerCounterMapType>::const_iterator fLastIndexSearched;
|
||||
InnerCounterMapType::const_iterator fLowerBoundTime;
|
||||
G4bool fLowerBoundSet;
|
||||
};
|
||||
G4bool SearchIndexUpdated(Search&, const TIndex&) const;
|
||||
G4int SearchUpperBoundTime(Search&, G4double, G4bool) const;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// #include "G4VUserMoleculeCounter.icc"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
G4VUserMoleculeCounter<T>::G4VUserMoleculeCounter() : G4VMoleculeCounter()
|
||||
{}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
G4VUserMoleculeCounter<T>::G4VUserMoleculeCounter(G4String name, MoleculeCounterType type)
|
||||
: G4VMoleculeCounter(name, type)
|
||||
{}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename TIndex>
|
||||
void G4VUserMoleculeCounter<TIndex>::Initialize()
|
||||
{
|
||||
InitializeUser();
|
||||
fIsInitialized = true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename TIndex>
|
||||
G4int G4VUserMoleculeCounter<TIndex>::GetNbMoleculesAtTime(const TIndex& index, G4double time) const
|
||||
{
|
||||
Search search = {};
|
||||
return GetNbMoleculesAtTime(search, index, time);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename TIndex>
|
||||
G4int G4VUserMoleculeCounter<TIndex>::GetNbMoleculesAtTime(Search& search, const TIndex& index,
|
||||
G4double time) const
|
||||
{
|
||||
G4bool sameIndex = !SearchIndexUpdated(search, index);
|
||||
return SearchUpperBoundTime(search, time, sameIndex);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename TIndex>
|
||||
std::vector<G4int>
|
||||
G4VUserMoleculeCounter<TIndex>::GetNbMoleculesAtTimes(const TIndex& index,
|
||||
const std::vector<G4double>& times) const
|
||||
{
|
||||
Search search = {};
|
||||
std::vector<G4int> counts = {};
|
||||
for (auto time : times)
|
||||
counts.push_back(GetNbMoleculesAtTime(search, index, time));
|
||||
return counts;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename TIndex>
|
||||
void G4VUserMoleculeCounter<TIndex>::AddMolecule(
|
||||
std::unique_ptr<G4VMoleculeCounter::G4VMoleculeCounterIndex> pIndex, G4double time, G4int number)
|
||||
{
|
||||
const TIndex* mapIndex = dynamic_cast<TIndex*>(pIndex.get());
|
||||
|
||||
if(mapIndex == nullptr)
|
||||
{
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "mapIndex is not found "<< G4endl;
|
||||
G4Exception(G4String("G4VUserMoleculeCounter<"
|
||||
+ G4::MoleculeCounter::GetTemplateTypeName<TIndex>() + ">::AddMolecule"),
|
||||
"mapIndex == nullptr", FatalException, errMsg);
|
||||
}else{
|
||||
if (G4::MoleculeCounter::Contains(fIgnoredMolecules, mapIndex->GetMolecule()->GetDefinition())
|
||||
|| G4::MoleculeCounter::Contains(fIgnoredReactants, mapIndex->GetMolecule()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (fCheckTimeIsConsistentWithScheduler && G4Scheduler::Instance()->IsRunning()
|
||||
&& std::fabs(time - G4Scheduler::Instance()->GetGlobalTime())
|
||||
> G4Scheduler::Instance()->GetTimeTolerance())
|
||||
{
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "Time of species " << mapIndex->GetMolecule()->GetName() << " is "
|
||||
<< G4BestUnit(time, "Time") << "while the global time is "
|
||||
<< G4BestUnit(G4Scheduler::Instance()->GetGlobalTime(), "Time") << G4endl;
|
||||
G4Exception(G4String("G4VUserMoleculeCounter<"
|
||||
+ G4::MoleculeCounter::GetTemplateTypeName<TIndex>() + ">::AddMolecule"),
|
||||
"TIME_DONT_MATCH", FatalException, errMsg);
|
||||
}
|
||||
|
||||
if (IsTimeAboveUpperBound(time)) {
|
||||
if (fVerbose > 3) {
|
||||
G4cout << "G4VUserMoleculeCounter<" << G4::MoleculeCounter::GetTemplateTypeName<TIndex>()
|
||||
<< ">(" << GetName() << ")::AddMolecule : " << mapIndex->GetMolecule()->GetName()
|
||||
<< " at time : " << G4BestUnit(time, "Time") << G4endl;
|
||||
G4cout << ":: [IsTimeAboveUpperBound] Skipping since IsTimeAboveUpperBound == true"
|
||||
<< G4endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (IsTimeBelowLowerBound(time)) {
|
||||
// put into shadow counter
|
||||
auto [it, indexIsNew] = fShadowCounterMap.emplace(*mapIndex, number);
|
||||
if (!indexIsNew) it->second += number;
|
||||
if (fVerbose > 3) {
|
||||
G4cout << ":: [IsTimeBelowLowerBound] Adding " << mapIndex->GetInfo()
|
||||
<< " shadow count: " << it->second - number << " + " << number << G4endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (fVerbose > 1) {
|
||||
G4cout << "G4VUserMoleculeCounter<" << G4::MoleculeCounter::GetTemplateTypeName<TIndex>()
|
||||
<< ">(" << GetName() << ")::AddMolecule : " << mapIndex->GetMolecule()->GetName()
|
||||
<< " at time : " << G4BestUnit(time, "Time") << G4endl;
|
||||
}
|
||||
|
||||
// within time bounds && not-ignored molecule
|
||||
// -> continue
|
||||
|
||||
auto it_shadow = fShadowCounterMap.find(*mapIndex);
|
||||
auto [it, indexIsNew] = fCounterMap.emplace(*mapIndex, InnerCounterMapType{fTimeComparer});
|
||||
|
||||
if (it_shadow != fShadowCounterMap.end()) {
|
||||
// entry found in shadow counter
|
||||
if (indexIsNew) {
|
||||
// mapIndex is new, initialize with shadow counter
|
||||
it->second[fActiveLowerBound] = it_shadow->second;
|
||||
}
|
||||
else {
|
||||
// mapIndex existed, we need to add the shadow count to it
|
||||
// this happens if we are in a subsequent event and have just crossed over the lower
|
||||
// activity bound the counter has then already entries from the previous event
|
||||
InnerCounterMapType::iterator it_time;
|
||||
G4bool timeIsNew;
|
||||
std::tie(it_time, timeIsNew) = it->second.emplace(fActiveLowerBound, 0);
|
||||
do {
|
||||
it_time->second += it_shadow->second;
|
||||
} while (++it_time != it->second.end());
|
||||
}
|
||||
// either way, remove the shadow count
|
||||
fShadowCounterMap.erase(it_shadow);
|
||||
}
|
||||
|
||||
// map for index existed (and was not empty)
|
||||
if (G4MoleculeCounterManager::Instance()->GetResetCountersBeforeEvent())
|
||||
// can only do consistency check if the counters are cleared for each event (= chem run)
|
||||
{
|
||||
auto end = it->second.rbegin();
|
||||
auto init_n = end == it->second.rend() ? 0 : end->second;
|
||||
|
||||
auto [it_time, timeIsNew] = it->second.emplace(time, init_n);
|
||||
it_time->second += number;
|
||||
|
||||
if (fCheckRecordedTimesAreConsistent
|
||||
&& !(end->first <= time
|
||||
|| std::fabs(end->first - time) <= fTimeComparer.GetPrecisionAtTime(time)))
|
||||
// Case 1 = new time comes after last recorded data
|
||||
// Case 2 = new time is about the same as the last recorded one
|
||||
{
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "Time of species " << mapIndex->GetMolecule()->GetName() << " is "
|
||||
<< G4BestUnit(time, "Time") << "while the global time is "
|
||||
<< G4BestUnit(G4Scheduler::Instance()->GetGlobalTime(), "Time")
|
||||
<< "(last counter time: " << G4BestUnit(end->first, "Time") << ")" << G4endl;
|
||||
G4Exception(G4String("G4VUserMoleculeCounter<"
|
||||
+ G4::MoleculeCounter::GetTemplateTypeName<TIndex>()
|
||||
+ ">::AddMolecule"),
|
||||
"TIME_DONT_MATCH", FatalException, errMsg);
|
||||
}
|
||||
}
|
||||
else // counters are not (automatically) reset by manager
|
||||
{
|
||||
// since counters are not cleared after chemical run (i.e., after event)
|
||||
// there will already be numbers in the map, so...
|
||||
// (1) find the closest time
|
||||
// (2) emplace entry using closest value as init + number
|
||||
// (3) add number to all "future" entries as well
|
||||
if (it->second.empty()) {
|
||||
it->second.emplace(time, number);
|
||||
}
|
||||
else { // at least one element exists, so we can try to find the closest key
|
||||
auto it_closest = G4::MoleculeCounter::FindClosestEntryForKey(it->second, time);
|
||||
auto [it_time, _] = it->second.emplace(time, it_closest->second);
|
||||
do {
|
||||
it_time->second += number;
|
||||
} while (++it_time != it->second.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename TIndex>
|
||||
void G4VUserMoleculeCounter<TIndex>::RemoveMolecule(
|
||||
std::unique_ptr<G4VMoleculeCounter::G4VMoleculeCounterIndex> pIndex, G4double time, G4int number)
|
||||
{
|
||||
const TIndex* mapIndex = dynamic_cast<TIndex*>(pIndex.get());
|
||||
|
||||
if(mapIndex == nullptr)
|
||||
{
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "mapIndex is not found "<< G4endl;
|
||||
G4Exception(G4String("G4VUserMoleculeCounter<"
|
||||
+ G4::MoleculeCounter::GetTemplateTypeName<TIndex>() + ">::AddMolecule"),
|
||||
"mapIndex == nullptr", FatalException, errMsg);
|
||||
}else{
|
||||
if (G4::MoleculeCounter::Contains(fIgnoredMolecules, mapIndex->GetMolecule()->GetDefinition())
|
||||
|| G4::MoleculeCounter::Contains(fIgnoredReactants, mapIndex->GetMolecule()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (fCheckTimeIsConsistentWithScheduler && G4Scheduler::Instance()->IsRunning()
|
||||
&& std::fabs(time - G4Scheduler::Instance()->GetGlobalTime())
|
||||
> G4Scheduler::Instance()->GetTimeTolerance())
|
||||
{
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "Time of species " << mapIndex->GetMolecule()->GetName() << " is "
|
||||
<< G4BestUnit(time, "Time") << "while the global time is "
|
||||
<< G4BestUnit(G4Scheduler::Instance()->GetGlobalTime(), "Time") << G4endl;
|
||||
G4Exception(G4String("G4VUserMoleculeCounter<"
|
||||
+ G4::MoleculeCounter::GetTemplateTypeName<TIndex>()
|
||||
+ ">::RemoveMolecule"),
|
||||
"TIME_DONT_MATCH", FatalException, errMsg);
|
||||
}
|
||||
|
||||
if (IsTimeBelowLowerBound(time)) {
|
||||
auto it = fShadowCounterMap.find(*mapIndex);
|
||||
if (it == fShadowCounterMap.end()) {
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "There was no " << mapIndex->GetMolecule()->GetName()
|
||||
<< " recorded at the time or even before the time asked" << G4endl;
|
||||
G4Exception(G4String("G4VUserMoleculeCounter<"
|
||||
+ G4::MoleculeCounter::GetTemplateTypeName<TIndex>()
|
||||
+ ">::RemoveMolecule"),
|
||||
"", FatalErrorInArgument, errMsg);
|
||||
}
|
||||
else {
|
||||
if (fVerbose > 3) {
|
||||
G4cout << ":: [IsTimeBelowLowerBound] Removing " << mapIndex->GetInfo()
|
||||
<< " shadow count: " << it->second << " - " << number << G4endl;
|
||||
}
|
||||
it->second -= number;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (IsTimeAboveUpperBound(time)) {
|
||||
// if the "active" counter was not filled, add the shadow counter to it at the lower bound
|
||||
// only needed for remove since remove will always be called at the end when the molecule is
|
||||
// destroyed
|
||||
auto [it, indexIsNew] = fCounterMap.emplace(*mapIndex, InnerCounterMapType{fTimeComparer});
|
||||
if (indexIsNew || it->second.empty()) {
|
||||
auto it_shadow = fShadowCounterMap.find(*mapIndex);
|
||||
if (it_shadow != fShadowCounterMap.end()) {
|
||||
it->second[fActiveLowerBound] = it_shadow->second;
|
||||
if (fVerbose > 3) {
|
||||
G4cout << ":: [IsTimeAboveUpperBound] Set " << mapIndex->GetInfo()
|
||||
<< " Map[ActiveLowerBound] with shadow count:" << it_shadow->second << G4endl;
|
||||
}
|
||||
fShadowCounterMap.erase(it_shadow);
|
||||
}
|
||||
else if (fVerbose > 3) {
|
||||
G4cout << ":: [IsTimeAboveUpperBound] Not updating with shadow count since"
|
||||
" no shadow count was found!"
|
||||
<< G4endl;
|
||||
}
|
||||
}
|
||||
else if (fVerbose > 3) {
|
||||
G4cout << ":: [IsTimeAboveUpperBound] Not updating with shadow count"
|
||||
" since it already exists "
|
||||
<< G4endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (fVerbose > 2) {
|
||||
G4cout << "G4VUserMoleculeCounter<" << G4::MoleculeCounter::GetTemplateTypeName<TIndex>()
|
||||
<< ">(" << GetName() << ")::RemoveMolecule : " << mapIndex->GetMolecule()->GetName()
|
||||
<< " at time : " << G4BestUnit(time, "Time") << G4endl;
|
||||
}
|
||||
|
||||
// within time bounds && not-ignored molecule
|
||||
// -> continue
|
||||
|
||||
auto it_shadow = fShadowCounterMap.find(*mapIndex);
|
||||
auto it = fCounterMap.find(*mapIndex);
|
||||
|
||||
if (it_shadow != fShadowCounterMap.end()) {
|
||||
// entry found in shadow counter
|
||||
if (it == fCounterMap.end()) {
|
||||
// no mapIndex found, initialize with shadow counter
|
||||
G4bool indexIsNew = false;
|
||||
std::tie(it, indexIsNew) =
|
||||
fCounterMap.emplace(*mapIndex, InnerCounterMapType{fTimeComparer});
|
||||
if (!indexIsNew) {
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "We tried to emplace the index after it was found to not exist, but now it "
|
||||
"says it existed!?"
|
||||
<< G4endl;
|
||||
G4Exception(G4String("G4VUserMoleculeCounter<"
|
||||
+ G4::MoleculeCounter::GetTemplateTypeName<TIndex>()
|
||||
+ ">::RemoveMolecule"),
|
||||
"NONSENSICAL", FatalErrorInArgument, errMsg);
|
||||
}
|
||||
it->second[fActiveLowerBound] = it_shadow->second;
|
||||
}
|
||||
else { // it != fCounterMap.end()
|
||||
// mapIndex exists, we need to add the shadow count to it
|
||||
// this happens if we are in a subsequent event and have just crossed over the lower
|
||||
// activity bound the counter has then already entries from the previous event
|
||||
auto [it_time, _] = it->second.emplace(fActiveLowerBound, 0);
|
||||
do {
|
||||
it_time->second += it_shadow->second;
|
||||
} while (++it_time != it->second.end());
|
||||
}
|
||||
|
||||
// either way, remove the shadow count
|
||||
fShadowCounterMap.erase(it_shadow);
|
||||
|
||||
// if (it_shadow != fShadowCounterMap.end()) {
|
||||
// G4bool indexIsNew = false;
|
||||
// // auto [it_, indexIsNew] = fCounterMap.emplace(*mapIndex,
|
||||
// // InnerCounterMapType{fTimeComparer});
|
||||
// std::tie(it, indexIsNew) = fCounterMap.emplace(*mapIndex,
|
||||
// InnerCounterMapType{fTimeComparer}); if (!indexIsNew) {
|
||||
// G4ExceptionDescription errMsg;
|
||||
// errMsg << "We tried to emplace the index after it was found to not exist, but now it
|
||||
// "
|
||||
// "says it existed!?"
|
||||
// << G4endl;
|
||||
// G4Exception(G4String("G4VUserMoleculeCounter<"
|
||||
// + G4::MoleculeCounter::GetTemplateTypeName<TIndex>()
|
||||
// + ">::RemoveMolecule"),
|
||||
// "NONSENSICAL", FatalErrorInArgument, errMsg);
|
||||
// }
|
||||
// it->second[fActiveLowerBound] = it_shadow->second;
|
||||
// // it = it_;
|
||||
// if (fVerbose > 3) {
|
||||
// G4cout << ":: Initialize " << mapIndex->GetInfo()
|
||||
// << " Map[ActiveLowerBound] with shadow count:" << it_shadow->second <<
|
||||
// G4endl;
|
||||
// }
|
||||
// fShadowCounterMap.erase(it_shadow);
|
||||
// }
|
||||
}
|
||||
|
||||
InnerCounterMapType& nbMolPerTime = it->second;
|
||||
InnerCounterMapType::iterator it_time;
|
||||
G4bool isNewTime = false;
|
||||
G4double oldTime = 0;
|
||||
|
||||
if (G4MoleculeCounterManager::Instance()->GetResetCountersBeforeEvent()) {
|
||||
auto end = nbMolPerTime.rbegin(); // get last entry
|
||||
oldTime = end->first;
|
||||
|
||||
// CHECK: no molecules have been recorded for this index
|
||||
if (end == nbMolPerTime.rend()) {
|
||||
if (fVerbose > 2) {
|
||||
mapIndex->GetMolecule()->PrintState();
|
||||
Dump();
|
||||
}
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "There was no " << mapIndex->GetMolecule()->GetName()
|
||||
<< " recorded at the time or even before the time asked" << G4endl;
|
||||
G4Exception("G4VUserMoleculeCounter::RemoveMolecule", "", FatalErrorInArgument, errMsg);
|
||||
}
|
||||
// CHECK: current time is less (by more than counter precision) than the most recently
|
||||
// recorded index
|
||||
if (fCheckRecordedTimesAreConsistent
|
||||
&& time - end->first < -fTimeComparer.GetPrecisionAtTime(time))
|
||||
{
|
||||
if (fVerbose > 2) {
|
||||
mapIndex->GetMolecule()->PrintState();
|
||||
Dump();
|
||||
}
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "Is time going back?? " << mapIndex->GetMolecule()->GetName()
|
||||
<< " is being removed at time " << G4BestUnit(time, "Time")
|
||||
<< "while last recorded time was " << G4BestUnit(end->first, "Time") << ".";
|
||||
G4Exception("G4VUserMoleculeCounter::RemoveMolecule", "RETURN_TO_THE_FUTUR",
|
||||
FatalErrorInArgument, errMsg);
|
||||
}
|
||||
std::tie(it_time, isNewTime) = nbMolPerTime.emplace(time, end->second);
|
||||
// auto oldNumber = it_time->second;
|
||||
it_time->second -= number;
|
||||
// if (time > 0.001)
|
||||
// G4cout << "(t=" << time << ")=" << number << " | old_it(t=" << it_time->first
|
||||
// << ") = " << oldNumber << " | timeIsNew=" << isNewTime
|
||||
// << " | new_it(t=" << it_time->first << ") = " << it_time->second << G4endl;
|
||||
}
|
||||
else {
|
||||
// since counters are not cleared after chemical run (i.e., after event)
|
||||
// there will already be numbers in the map, so...
|
||||
// (1) find the closest time
|
||||
// (2) emplace entry using closest value as init - number
|
||||
// (3) remove number from all "future" entries as well
|
||||
auto it_closest = G4::MoleculeCounter::FindClosestEntryForKey(nbMolPerTime, time);
|
||||
std::tie(it_time, isNewTime) = nbMolPerTime.emplace(time, it_closest->second);
|
||||
auto _it = it_time;
|
||||
do {
|
||||
_it->second -= number;
|
||||
} while (++_it != it->second.end());
|
||||
}
|
||||
|
||||
// Check that count at new time is >= 0
|
||||
// This currently throws tons of errors for non-basic counters.
|
||||
// auto it_time = nbMolPerTime.find(time);
|
||||
if (it_time == nbMolPerTime.end() || it_time->second < 0) {
|
||||
if (fVerbose > 2) Dump();
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "After removal of " << number << " species of "
|
||||
<< mapIndex->GetMolecule()->GetName() << " the final number at time "
|
||||
<< G4BestUnit(time, "Time") << " is less than zero and so not valid."
|
||||
<< "\nIndex was :" << mapIndex->GetInfo() << "\nGlobal time is "
|
||||
<< G4BestUnit(G4Scheduler::Instance()->GetGlobalTime(), "Time")
|
||||
<< "\nPrevious selected time is " << G4BestUnit(oldTime, "Time") << G4endl;
|
||||
if (fNegativeCountsAreFatal) {
|
||||
G4Exception(G4String("G4VUserMoleculeCounter<"
|
||||
+ G4::MoleculeCounter::GetTemplateTypeName<TIndex>()
|
||||
+ ">::RemoveMolecule"),
|
||||
"N_INF_0", FatalException, errMsg);
|
||||
}
|
||||
else if (fVerbose > 0) {
|
||||
G4Exception(G4String("G4VUserMoleculeCounter<"
|
||||
+ G4::MoleculeCounter::GetTemplateTypeName<TIndex>()
|
||||
+ ">::RemoveMolecule"),
|
||||
"N_INF_0", JustWarning, errMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename TIndex>
|
||||
void G4VUserMoleculeCounter<TIndex>::SchedulerFinalizedTracking()
|
||||
{
|
||||
// Add record to fCounterMap for each fShadowCounterMap index unless they exist already
|
||||
for (auto& it_shadow : fShadowCounterMap) {
|
||||
auto [it, indexIsNew] =
|
||||
fCounterMap.emplace(it_shadow.first, InnerCounterMapType{fTimeComparer});
|
||||
if (indexIsNew || it->second.empty()) {
|
||||
it->second[fActiveLowerBound] = it_shadow.second;
|
||||
if (fVerbose > 3) {
|
||||
G4cout << "G4VUserMoleculeCounter<" << G4::MoleculeCounter::GetTemplateTypeName<TIndex>()
|
||||
<< ">(" << GetName() << ")::SchedulerEndedTracking : " << "setting map index '"
|
||||
<< it_shadow.first.GetInfo() << "' from shadow counter to n = " << it_shadow.second
|
||||
<< G4endl;
|
||||
}
|
||||
}
|
||||
else if (fVerbose > 2) {
|
||||
G4cout << "G4VUserMoleculeCounter<" << G4::MoleculeCounter::GetTemplateTypeName<TIndex>()
|
||||
<< ">(" << GetName() << ")::SchedulerEndedTracking : "
|
||||
<< "encountered dangling shadow counter iterator for index '"
|
||||
<< it_shadow.first.GetInfo() << "'" << G4endl;
|
||||
}
|
||||
}
|
||||
fShadowCounterMap.clear();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename TIndex>
|
||||
std::vector<TIndex> G4VUserMoleculeCounter<TIndex>::GetMapIndices() const
|
||||
{
|
||||
if (fVerbose > 2) {
|
||||
G4cout << "Entering in G4VUserMoleculeCounter::GetMapIndices" << G4endl;
|
||||
}
|
||||
return G4::MoleculeCounter::GetMapIndices(fCounterMap);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
std::set<const G4MolecularConfiguration*> G4VUserMoleculeCounter<T>::GetRecordedMolecules() const
|
||||
{
|
||||
if (fVerbose > 2) {
|
||||
G4cout << "Entering in G4MoleculeCounter::RecordMolecules" << G4endl;
|
||||
}
|
||||
std::set<const G4MolecularConfiguration*> output{};
|
||||
for (const auto& it : fCounterMap) {
|
||||
output.insert(it.first.GetMolecule());
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
std::set<G4double> G4VUserMoleculeCounter<T>::GetRecordedTimes() const
|
||||
{
|
||||
return G4::MoleculeCounter::GetRecordedTimes<T>(fCounterMap);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
void G4VUserMoleculeCounter<T>::Dump() const
|
||||
{
|
||||
DumpCounterMapIndices();
|
||||
G4::MoleculeCounter::DumpCounterMapContents<T>(fCounterMap);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void G4VUserMoleculeCounter<T>::DumpCounterMapIndices() const
|
||||
{
|
||||
G4::MoleculeCounter::DumpCounterMapIndices<T>(fCounterMap);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
void G4VUserMoleculeCounter<T>::ResetCounter()
|
||||
{
|
||||
if (fVerbose > 1) {
|
||||
G4cout << "G4VUserMoleculeCounter<" << G4::MoleculeCounter::GetTemplateTypeName<T>() << ">("
|
||||
<< GetName() << ")::ResetCounter" << G4endl;
|
||||
}
|
||||
fCounterMap.clear();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename TIndex>
|
||||
G4bool G4VUserMoleculeCounter<TIndex>::SearchIndexUpdated(Search& search, const TIndex& index) const
|
||||
{
|
||||
if (search.fLowerBoundSet && !(search.fLastIndexSearched->first < index)
|
||||
&& !(index < search.fLastIndexSearched->first))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
auto mol_it = fCounterMap.find(index);
|
||||
search.fLastIndexSearched = mol_it;
|
||||
|
||||
if (mol_it != fCounterMap.end()) {
|
||||
search.fLowerBoundTime = search.fLastIndexSearched->second.end();
|
||||
search.fLowerBoundSet = true;
|
||||
}
|
||||
else {
|
||||
search.fLowerBoundSet = false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
G4int G4VUserMoleculeCounter<T>::SearchUpperBoundTime(Search& search, G4double time,
|
||||
G4bool sameIndex) const
|
||||
{
|
||||
auto mol_it = search.fLastIndexSearched;
|
||||
if (mol_it == fCounterMap.end()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
InnerCounterMapType const& timeMap = mol_it->second;
|
||||
if (timeMap.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sameIndex) {
|
||||
if (search.fLowerBoundSet && search.fLowerBoundTime != timeMap.end()) {
|
||||
if (search.fLowerBoundTime->first < time) {
|
||||
auto upperToLast = search.fLowerBoundTime;
|
||||
upperToLast++;
|
||||
|
||||
if (upperToLast == timeMap.end()) {
|
||||
return search.fLowerBoundTime->second;
|
||||
}
|
||||
|
||||
if (upperToLast->first > time) {
|
||||
return search.fLowerBoundTime->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto up_time_it = timeMap.upper_bound(time);
|
||||
|
||||
if (up_time_it == timeMap.end()) {
|
||||
auto last_time = timeMap.rbegin();
|
||||
return last_time->second;
|
||||
}
|
||||
if (up_time_it == timeMap.begin()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
up_time_it--;
|
||||
|
||||
search.fLowerBoundTime = up_time_it;
|
||||
search.fLowerBoundSet = true;
|
||||
|
||||
return search.fLowerBoundTime->second;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename TIndex>
|
||||
void G4VUserMoleculeCounter<TIndex>::AbsorbCounter(const G4VMoleculeCounterInternalBase* pCounterBase)
|
||||
{
|
||||
if (pCounterBase == nullptr) {
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "Could not cast the pointer to type G4VUserMoleculeCounter<"
|
||||
<< G4::MoleculeCounter::GetTemplateTypeName<TIndex>() << ">!\n"
|
||||
<< "Because the pointer is nullptr!" << G4endl;
|
||||
G4Exception(G4String("G4VUserMoleculeCounter<"
|
||||
+ G4::MoleculeCounter::GetTemplateTypeName<TIndex>() + ">::AbsorbCounter"),
|
||||
"BAD_REFERENCE", FatalException, errMsg);
|
||||
}
|
||||
|
||||
auto pCounter = dynamic_cast<G4VUserMoleculeCounter<TIndex> const*>(pCounterBase);
|
||||
|
||||
if (pCounter == nullptr) {
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "Could not cast the pointer to type G4VUserMoleculeCounter<"
|
||||
<< G4::MoleculeCounter::GetTemplateTypeName<TIndex>() << ">!\n"
|
||||
<< "Because the objects aren't of the same type!" << G4endl;
|
||||
G4Exception(G4String("G4VUserMoleculeCounter<"
|
||||
+ G4::MoleculeCounter::GetTemplateTypeName<TIndex>() + ">::AbsorbCounter"),
|
||||
"BAD_REFERENCE", FatalException, errMsg);
|
||||
}
|
||||
|
||||
if (pCounter->GetType() != GetType()) {
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "You are trying to absorb a counter with different type!" << G4endl;
|
||||
G4Exception(G4String("G4VUserMoleculeCounter<"
|
||||
+ G4::MoleculeCounter::GetTemplateTypeName<TIndex>() + ">::AbsorbCounter"),
|
||||
"TYPE_DIFF", JustWarning, errMsg);
|
||||
}
|
||||
|
||||
for (auto const& worker_it : pCounter->GetCounterMap()) {
|
||||
auto [master_it, indexIsNew] =
|
||||
fCounterMap.emplace(worker_it.first, InnerCounterMapType{fTimeComparer});
|
||||
|
||||
G4int currentNumber = 0, previousNumber = 0;
|
||||
for (auto const& [time, number] : worker_it.second) {
|
||||
currentNumber = number - previousNumber;
|
||||
previousNumber = number;
|
||||
|
||||
if (master_it->second.empty()) {
|
||||
master_it->second.emplace(time, currentNumber);
|
||||
}
|
||||
else { // at least one element exists, so we can try to find the closest key
|
||||
auto it_closest = G4::MoleculeCounter::FindClosestEntryForKey(master_it->second, time);
|
||||
auto [it, _] = master_it->second.emplace(time, it_closest->second);
|
||||
do {
|
||||
it->second += currentNumber;
|
||||
} while (++it != master_it->second.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#endif
|
||||
@@ -7,37 +7,49 @@ geant4_add_module(G4emdna-molman
|
||||
G4MolecularConfiguration.hh
|
||||
G4MolecularDissociationChannel.hh
|
||||
G4MolecularDissociationTable.hh
|
||||
G4MoleculeCounter.hh
|
||||
G4MoleculeDefinition.hh
|
||||
G4MoleculeFinder.hh
|
||||
G4MoleculeHandleManager.hh
|
||||
G4Molecule.hh
|
||||
G4MoleculeIterator.hh
|
||||
G4MoleculeTable.hh
|
||||
G4MoleculeTableMessenger.hh
|
||||
G4Serialize.hh
|
||||
G4VMolecularDissociationDisplacer.hh
|
||||
G4MoleculeCounterManager.hh
|
||||
G4MoleculeCounterManagerMessenger.hh
|
||||
G4MoleculeCounterTemplates.hh
|
||||
G4VMoleculeCounterInternalBase.hh
|
||||
G4VMoleculeCounter.hh
|
||||
G4MoleculeTableMessenger.hh
|
||||
G4VMoleculeReactionCounter.hh
|
||||
G4VUserMoleculeCounter.hh
|
||||
G4MoleculeCounter.hh
|
||||
G4MoleculeCounterTimeComparer.hh
|
||||
SOURCES
|
||||
G4MolecularConfiguration.cc
|
||||
G4MolecularDissociationChannel.cc
|
||||
G4MolecularDissociationTable.cc
|
||||
G4MoleculeCounter.cc
|
||||
G4Molecule.cc
|
||||
G4MoleculeDefinition.cc
|
||||
G4MoleculeHandleManager.cc
|
||||
G4MoleculeTable.cc
|
||||
G4MoleculeTableMessenger.cc
|
||||
G4Serialize.cc
|
||||
G4VMolecularDissociationDisplacer.cc
|
||||
G4MoleculeCounterManager.cc
|
||||
G4MoleculeCounterManagerMessenger.cc
|
||||
G4VMoleculeCounterInternalBase.cc
|
||||
G4VMoleculeCounter.cc
|
||||
G4MoleculeTableMessenger.cc)
|
||||
G4VMoleculeReactionCounter.cc
|
||||
G4MoleculeCounter.cc
|
||||
G4MoleculeCounterTimeComparer.cc)
|
||||
|
||||
geant4_module_link_libraries(G4emdna-molman
|
||||
PUBLIC
|
||||
G4emdna-man
|
||||
G4globman
|
||||
G4partman
|
||||
G4intercoms
|
||||
PRIVATE
|
||||
G4heprandom
|
||||
G4intercoms
|
||||
G4track)
|
||||
|
||||
@@ -48,12 +48,13 @@
|
||||
|
||||
#include "G4Molecule.hh"
|
||||
#include "G4MolecularConfiguration.hh"
|
||||
#include "G4MoleculeLocator.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4Track.hh"
|
||||
#include "G4VMoleculeCounter.hh"
|
||||
|
||||
//#include "G4DNAChemistryManager.hh"
|
||||
#include "G4MoleculeCounterManager.hh"
|
||||
using namespace std;
|
||||
|
||||
G4Allocator<G4Molecule>*& aMoleculeAllocator()
|
||||
@@ -154,12 +155,23 @@ G4Molecule::~G4Molecule()
|
||||
{
|
||||
if (fpTrack != nullptr)
|
||||
{
|
||||
if (G4VMoleculeCounter::Instance()->InUse())
|
||||
if (G4MoleculeCounterManager::Instance()->GetIsActive())
|
||||
{
|
||||
G4VMoleculeCounter::Instance()->
|
||||
RemoveAMoleculeAtTime(fpMolecularConfiguration,
|
||||
fpTrack->GetGlobalTime(),
|
||||
&(fpTrack->GetPosition()));
|
||||
switch (fpTrack->GetTrackStatus())
|
||||
{
|
||||
case fAlive:
|
||||
case fPostponeToNextEvent:
|
||||
case fStopButAlive:
|
||||
case fSuspend:
|
||||
// do not remove molecule count if the track is not being killed
|
||||
break;
|
||||
case fStopAndKill:
|
||||
case fKillTrackAndSecondaries:
|
||||
default:
|
||||
G4MoleculeCounterManager::Instance()->RemoveMolecule(fpTrack,
|
||||
fpTrack->GetGlobalTime());
|
||||
break;
|
||||
}
|
||||
}
|
||||
fpTrack = nullptr;
|
||||
}
|
||||
@@ -360,8 +372,9 @@ void G4Molecule::PrintState() const
|
||||
|
||||
//______________________________________________________________________________
|
||||
|
||||
G4Track* G4Molecule::BuildTrack(G4double globalTime,
|
||||
const G4ThreeVector& position)
|
||||
G4Track *G4Molecule::BuildTrack(G4double globalTime,
|
||||
const G4ThreeVector &position,
|
||||
const G4Track *parentTrack)
|
||||
{
|
||||
if (fpTrack != nullptr)
|
||||
{
|
||||
@@ -386,18 +399,35 @@ G4Track* G4Molecule::BuildTrack(G4double globalTime,
|
||||
fpMolecularConfiguration->GetDefinition(), MomentumDirection,
|
||||
KineticEnergy);
|
||||
|
||||
if (G4VMoleculeCounter::Instance()->InUse())
|
||||
{
|
||||
G4VMoleculeCounter::Instance()->
|
||||
AddAMoleculeAtTime(fpMolecularConfiguration,
|
||||
globalTime,
|
||||
&(fpTrack->GetPosition()));
|
||||
}
|
||||
|
||||
//Set the Track
|
||||
// Set the Track
|
||||
fpTrack = new G4Track(dynamicParticle, globalTime, position);
|
||||
fpTrack->SetUserInformation(this);
|
||||
|
||||
// Copy over touchable handle (see G4VEmProcess)
|
||||
if (parentTrack == nullptr || parentTrack->GetTouchable() == nullptr ||
|
||||
position != parentTrack->GetPosition())
|
||||
{
|
||||
// If (1) no track or touchable handle exists, or
|
||||
// If (2) the new position is inconsistent with the track's position
|
||||
// create a new touchable from the position:
|
||||
// this way the subsequent calls *should* properly see its location (i.e. PV)
|
||||
G4MoleculeLocator::Instance()->LocateMoleculeSetStateAndTouchable(fpTrack);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpTrack->SetTouchableHandle(parentTrack->GetTouchableHandle());
|
||||
}
|
||||
|
||||
if (G4MoleculeCounterManager::Instance()->GetIsActive())
|
||||
{
|
||||
G4MoleculeCounterManager::Instance()->AddMolecule(fpTrack,
|
||||
fpTrack->GetGlobalTime());
|
||||
// G4VMoleculeCounter::Instance()->
|
||||
// AddAMoleculeAtTime(fpMolecularConfiguration,
|
||||
// globalTime,
|
||||
// &(fpTrack->GetPosition()));
|
||||
}
|
||||
|
||||
return fpTrack;
|
||||
}
|
||||
|
||||
|
||||
+25
-459
@@ -23,486 +23,52 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// Author: Mathieu Karamitros
|
||||
// Modified by Christian Velten on 10/27/2024.
|
||||
//
|
||||
|
||||
#include "G4MoleculeCounter.hh"
|
||||
|
||||
#include "G4MolecularConfiguration.hh"
|
||||
#include "G4MoleculeDefinition.hh"
|
||||
#include "G4Molecule.hh"
|
||||
#include "G4MoleculeTable.hh"
|
||||
#include "G4Scheduler.hh" // TODO: remove this dependency
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4UIcommand.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
|
||||
#include <iomanip>
|
||||
#include <memory>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace G4{
|
||||
namespace MoleculeCounter {
|
||||
|
||||
bool TimePrecision::operator()(const double& a, const double& b) const
|
||||
{
|
||||
if (std::fabs(a - b) < fPrecision)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return a < b;
|
||||
}
|
||||
|
||||
G4ThreadLocal double TimePrecision::fPrecision = 0.5 * picosecond;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
G4MoleculeCounter* G4MoleculeCounter::Instance()
|
||||
|
||||
G4MoleculeCounter::G4MoleculeCounter() : G4VUserMoleculeCounter() {}
|
||||
|
||||
G4MoleculeCounter::G4MoleculeCounter(G4String name)
|
||||
: G4VUserMoleculeCounter(name, MoleculeCounterType::Basic)
|
||||
{}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4MoleculeCounter::InitializeUser() {}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
std::unique_ptr<G4VMoleculeCounter::G4VMoleculeCounterIndex>
|
||||
G4MoleculeCounter::BuildIndex(const G4Track* aTrack) const
|
||||
{
|
||||
if (fpInstance == nullptr)
|
||||
{
|
||||
fpInstance = new G4MoleculeCounter();
|
||||
}
|
||||
return dynamic_cast<G4MoleculeCounter*>(fpInstance);
|
||||
return std::make_unique<G4MoleculeCounterIndex>(GetMolecule(aTrack)->GetMolecularConfiguration());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
G4MoleculeCounter::G4MoleculeCounter()
|
||||
std::unique_ptr<G4VMoleculeCounter::G4VMoleculeCounterIndex>
|
||||
G4MoleculeCounter::BuildIndex(const G4Track* aTrack, const G4StepPoint*) const
|
||||
{
|
||||
fVerbose = 0;
|
||||
fCheckTimeIsConsistentWithScheduler = true;
|
||||
return BuildIndex(aTrack);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
G4MoleculeCounter::~G4MoleculeCounter() = default;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4MoleculeCounter::Initialize()
|
||||
std::unique_ptr<G4VMoleculeCounter::G4VMoleculeCounterIndex>
|
||||
G4MoleculeCounter::BuildSimpleIndex(const G4MolecularConfiguration* configuration) const
|
||||
{
|
||||
auto mol_iterator = G4MoleculeTable::Instance()->GetConfigurationIterator();
|
||||
while ((mol_iterator)())
|
||||
{
|
||||
if (!IsRegistered(mol_iterator.value()->GetDefinition()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
fCounterMap[mol_iterator.value()]; // initialize the second map
|
||||
}
|
||||
return std::make_unique<G4MoleculeCounterIndex>(configuration);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4MoleculeCounter::SetTimeSlice(double timeSlice)
|
||||
{
|
||||
G4::MoleculeCounter::TimePrecision::fPrecision = timeSlice;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
G4bool G4MoleculeCounter::SearchTimeMap(Reactant* molecule)
|
||||
{
|
||||
if (fpLastSearch == nullptr)
|
||||
{
|
||||
fpLastSearch = std::make_unique<Search>();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fpLastSearch->fLowerBoundSet &&
|
||||
fpLastSearch->fLastMoleculeSearched->first == molecule)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
auto mol_it = fCounterMap.find(molecule);
|
||||
fpLastSearch->fLastMoleculeSearched = mol_it;
|
||||
|
||||
if (mol_it != fCounterMap.end())
|
||||
{
|
||||
fpLastSearch->fLowerBoundTime = fpLastSearch->fLastMoleculeSearched->second
|
||||
.end();
|
||||
fpLastSearch->fLowerBoundSet = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fpLastSearch->fLowerBoundSet = false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
int G4MoleculeCounter::SearchUpperBoundTime(double time,
|
||||
bool sameTypeOfMolecule)
|
||||
{
|
||||
auto mol_it = fpLastSearch->fLastMoleculeSearched;
|
||||
if (mol_it == fCounterMap.end())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
NbMoleculeAgainstTime& timeMap = mol_it->second;
|
||||
if (timeMap.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sameTypeOfMolecule)
|
||||
{
|
||||
if (fpLastSearch->fLowerBoundSet && fpLastSearch->fLowerBoundTime != timeMap.end())
|
||||
{
|
||||
if (fpLastSearch->fLowerBoundTime->first < time)
|
||||
{
|
||||
auto upperToLast = fpLastSearch->fLowerBoundTime;
|
||||
upperToLast++;
|
||||
|
||||
if (upperToLast == timeMap.end())
|
||||
{
|
||||
return fpLastSearch->fLowerBoundTime->second;
|
||||
}
|
||||
|
||||
if (upperToLast->first > time)
|
||||
{
|
||||
return fpLastSearch->fLowerBoundTime->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto up_time_it = timeMap.upper_bound(time);
|
||||
|
||||
if (up_time_it == timeMap.end())
|
||||
{
|
||||
auto last_time = timeMap.rbegin();
|
||||
return last_time->second;
|
||||
}
|
||||
if (up_time_it == timeMap.begin())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
up_time_it--;
|
||||
|
||||
fpLastSearch->fLowerBoundTime = up_time_it;
|
||||
fpLastSearch->fLowerBoundSet = true;
|
||||
|
||||
return fpLastSearch->fLowerBoundTime->second;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
int G4MoleculeCounter::GetNMoleculesAtTime(Reactant* molecule,
|
||||
double time)
|
||||
{
|
||||
G4bool sameTypeOfMolecule = SearchTimeMap(molecule);
|
||||
return SearchUpperBoundTime(time, sameTypeOfMolecule);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4MoleculeCounter::AddAMoleculeAtTime(Reactant* molecule,
|
||||
G4double time,
|
||||
const G4ThreeVector* /*position*/,
|
||||
int number)
|
||||
{
|
||||
if (fDontRegister[molecule->GetDefinition()])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (fVerbose != 0)
|
||||
{
|
||||
G4cout << "G4MoleculeCounter::AddAMoleculeAtTime : " << molecule->GetName()
|
||||
<< " at time : " << G4BestUnit(time, "Time") << G4endl;
|
||||
}
|
||||
|
||||
auto counterMap_i = fCounterMap.find(molecule);
|
||||
|
||||
if (counterMap_i == fCounterMap.end())
|
||||
{
|
||||
fCounterMap[molecule][time] = number;
|
||||
}
|
||||
else if (counterMap_i->second.empty())
|
||||
{
|
||||
counterMap_i->second[time] = number;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto end = counterMap_i->second.rbegin();
|
||||
|
||||
if (end->first <= time ||
|
||||
fabs(end->first - time) <= G4::MoleculeCounter::TimePrecision::fPrecision)
|
||||
// Case 1 = new time comes after last recorded data
|
||||
// Case 2 = new time is about the same as the last recorded one
|
||||
{
|
||||
double newValue = end->second + number;
|
||||
counterMap_i->second[time] = newValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if(fabs(time - G4Scheduler::Instance()->GetGlobalTime()) >
|
||||
// G4Scheduler::Instance()->GetTimeTolerance())
|
||||
{
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "Time of species "
|
||||
<< molecule->GetName() << " is "
|
||||
<< G4BestUnit(time, "Time") << " while "
|
||||
<< " global time is "
|
||||
<< G4BestUnit(G4Scheduler::Instance()->GetGlobalTime(), "Time")
|
||||
<< G4endl;
|
||||
G4Exception("G4MoleculeCounter::AddAMoleculeAtTime",
|
||||
"TIME_DONT_MATCH",
|
||||
FatalException, errMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4MoleculeCounter::RemoveAMoleculeAtTime(const G4MolecularConfiguration* pMolecule,
|
||||
G4double time,
|
||||
const G4ThreeVector* /*position*/,
|
||||
int number)
|
||||
{
|
||||
if (fDontRegister[pMolecule->GetDefinition()])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (fVerbose != 0)
|
||||
{
|
||||
G4cout << "G4MoleculeCounter::RemoveAMoleculeAtTime : "
|
||||
<< pMolecule->GetName() << " at time : " << G4BestUnit(time, "Time")
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
if (fCheckTimeIsConsistentWithScheduler)
|
||||
{
|
||||
if (fabs(time - G4Scheduler::Instance()->GetGlobalTime()) >
|
||||
G4Scheduler::Instance()->GetTimeTolerance())
|
||||
{
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "Time of species "
|
||||
<< pMolecule->GetName() << " is "
|
||||
<< G4BestUnit(time, "Time") << " while "
|
||||
<< " global time is "
|
||||
<< G4BestUnit(G4Scheduler::Instance()->GetGlobalTime(), "Time")
|
||||
<< G4endl;
|
||||
G4Exception("G4MoleculeCounter::RemoveAMoleculeAtTime",
|
||||
"TIME_DONT_MATCH",
|
||||
FatalException, errMsg);
|
||||
}
|
||||
}
|
||||
|
||||
NbMoleculeAgainstTime& nbMolPerTime = fCounterMap[pMolecule];
|
||||
|
||||
if (nbMolPerTime.empty())
|
||||
{
|
||||
pMolecule->PrintState();
|
||||
Dump();
|
||||
G4String errMsg =
|
||||
"You are trying to remove molecule " + pMolecule->GetName() +
|
||||
" from the counter while this kind of molecules has not been registered yet";
|
||||
G4Exception("G4MoleculeCounter::RemoveAMoleculeAtTime", "",
|
||||
FatalErrorInArgument, errMsg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = nbMolPerTime.rbegin();
|
||||
|
||||
if (it == nbMolPerTime.rend())
|
||||
{
|
||||
it--;
|
||||
|
||||
G4String errMsg =
|
||||
"There was no " + pMolecule->GetName() + " recorded at the time or even before the time asked";
|
||||
G4Exception("G4MoleculeCounter::RemoveAMoleculeAtTime", "",
|
||||
FatalErrorInArgument, errMsg);
|
||||
}
|
||||
|
||||
if (time - it->first < -G4::MoleculeCounter::TimePrecision::fPrecision)
|
||||
{
|
||||
Dump();
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "Is time going back?? " << pMolecule->GetName()
|
||||
<< " is being removed at time " << G4BestUnit(time, "Time")
|
||||
<< " while last recorded time was "
|
||||
<< G4BestUnit(it->first, "Time") << ".";
|
||||
G4Exception("G4MoleculeCounter::RemoveAMoleculeAtTime",
|
||||
"RETURN_TO_THE_FUTUR",
|
||||
FatalErrorInArgument,
|
||||
errMsg);
|
||||
}
|
||||
|
||||
double finalN = it->second - number;
|
||||
|
||||
if (finalN < 0)
|
||||
{
|
||||
Dump();
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "After removal of " << number << " species of "
|
||||
<< pMolecule->GetName() << " the final number at time "
|
||||
<< G4BestUnit(time, "Time") << " is less than zero and so not valid."
|
||||
<< " Global time is "
|
||||
<< G4BestUnit(G4Scheduler::Instance()->GetGlobalTime(), "Time")
|
||||
<< ". Previous selected time is "
|
||||
<< G4BestUnit(it->first, "Time")
|
||||
<< G4endl;
|
||||
G4Exception("G4MoleculeCounter::RemoveAMoleculeAtTime",
|
||||
"N_INF_0",
|
||||
FatalException, errMsg);
|
||||
}
|
||||
|
||||
nbMolPerTime[time] = finalN;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
G4MoleculeCounter::RecordedMolecules G4MoleculeCounter::GetRecordedMolecules()
|
||||
{
|
||||
if (fVerbose > 1)
|
||||
{
|
||||
G4cout << "Entering in G4MoleculeCounter::RecordMolecules" << G4endl;
|
||||
}
|
||||
|
||||
RecordedMolecules output(new ReactantList());
|
||||
|
||||
for (const auto & it : fCounterMap)
|
||||
{
|
||||
output->push_back(it.first);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
RecordedTimes G4MoleculeCounter::GetRecordedTimes()
|
||||
{
|
||||
RecordedTimes output(new std::set<G4double>);
|
||||
|
||||
for(const auto& it : fCounterMap)
|
||||
{
|
||||
for(const auto& it2 : it.second)
|
||||
{
|
||||
//time = it2->first;
|
||||
output->insert(it2.first);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// >>DEV<<
|
||||
//void G4MoleculeCounter::SignalReceiver(G4SpeciesInCM* /*speciesInCM*/,
|
||||
// size_t moleculeID,
|
||||
// int /*number*/,
|
||||
// G4SpeciesInCM::SpeciesChange speciesChange,
|
||||
// int diff)
|
||||
//{
|
||||
// switch(speciesChange)
|
||||
// {
|
||||
// case G4SpeciesInCM::eAdd:
|
||||
// AddAMoleculeAtTime(G4MoleculeTable::Instance()->GetConfiguration((int)moleculeID),
|
||||
// G4Scheduler::Instance()->GetGlobalTime(),
|
||||
// diff);
|
||||
// break;
|
||||
// case G4SpeciesInCM::eRemove:
|
||||
// RemoveAMoleculeAtTime(G4MoleculeTable::Instance()->GetConfiguration((int)moleculeID),
|
||||
// G4Scheduler::Instance()->GetGlobalTime(),
|
||||
// diff);
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4MoleculeCounter::Dump()
|
||||
{
|
||||
for (const auto& it : fCounterMap)
|
||||
{
|
||||
auto pReactant = it.first;
|
||||
|
||||
G4cout << " --- > For " << pReactant->GetName() << G4endl;
|
||||
|
||||
for (const auto& it2 : it.second)
|
||||
{
|
||||
G4cout << " " << G4BestUnit(it2.first, "Time")
|
||||
<< " " << it2.second << G4endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4MoleculeCounter::ResetCounter()
|
||||
{
|
||||
if (fVerbose != 0)
|
||||
{
|
||||
G4cout << " ---> G4MoleculeCounter::ResetCounter" << G4endl;
|
||||
}
|
||||
fCounterMap.clear();
|
||||
fpLastSearch.reset(nullptr);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const NbMoleculeAgainstTime& G4MoleculeCounter::GetNbMoleculeAgainstTime(Reactant* molecule)
|
||||
{
|
||||
return fCounterMap[molecule];
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4MoleculeCounter::SetVerbose(G4int level)
|
||||
{
|
||||
fVerbose = level;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
G4int G4MoleculeCounter::GetVerbose()
|
||||
{
|
||||
return fVerbose;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4MoleculeCounter::DontRegister(const G4MoleculeDefinition* molDef)
|
||||
{
|
||||
fDontRegister[molDef] = true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool G4MoleculeCounter::IsRegistered(const G4MoleculeDefinition* molDef)
|
||||
{
|
||||
return fDontRegister.find(molDef) == fDontRegister.end();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4MoleculeCounter::RegisterAll()
|
||||
{
|
||||
fDontRegister.clear();
|
||||
}
|
||||
|
||||
G4bool G4MoleculeCounter::IsTimeCheckedForConsistency() const
|
||||
{
|
||||
return fCheckTimeIsConsistentWithScheduler;
|
||||
}
|
||||
|
||||
void G4MoleculeCounter::CheckTimeForConsistency(G4bool flag)
|
||||
{
|
||||
fCheckTimeIsConsistentWithScheduler = flag;
|
||||
}
|
||||
|
||||
|
||||
+711
@@ -0,0 +1,711 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// Author: Christian Velten (2025)
|
||||
|
||||
#include "G4MoleculeCounterManager.hh"
|
||||
|
||||
#include "G4AutoLock.hh"
|
||||
#include "G4MoleculeCounterManagerMessenger.hh"
|
||||
#include "G4MoleculeCounterTemplates.hh"
|
||||
#include "G4StateManager.hh"
|
||||
#include "G4Step.hh"
|
||||
#include "G4Threading.hh"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static G4Mutex managerInstance;
|
||||
static G4Mutex masterInstanceMutex;
|
||||
static G4Mutex workerInstancesMutex;
|
||||
|
||||
const G4MoleculeCounterManager* G4MoleculeCounterManager::fpMasterInstance = nullptr;
|
||||
std::vector<const G4MoleculeCounterManager*> G4MoleculeCounterManager::fWorkerInstances = {};
|
||||
G4ThreadLocal std::unique_ptr<G4MoleculeCounterManager> G4MoleculeCounterManager::fpInstance = nullptr;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
G4ThreadLocal std::atomic<G4bool> G4MoleculeCounterManager::fBeginOfEventTriggered(false);
|
||||
std::atomic<G4bool> G4MoleculeCounterManager::fBeginOfRunTriggered(false);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// CTOR & INSTANCE
|
||||
//
|
||||
|
||||
G4MoleculeCounterManager::G4MoleculeCounterManager(G4MoleculeCounterManager::Private)
|
||||
: fVerbosity(0), fIsInitialized(false), fIsActive(true)
|
||||
{
|
||||
fpMessenger = std::make_unique<G4MoleculeCounterManagerMessenger>(this);
|
||||
}
|
||||
|
||||
G4MoleculeCounterManager::~G4MoleculeCounterManager()
|
||||
{
|
||||
// The manager owns all the counters as raw pointers, clean up:
|
||||
DeregisterAllCounters();
|
||||
|
||||
if (fVerbosity > 0) {
|
||||
if (GetResetCountersBeforeRun() && !fBeginOfRunTriggered.load()) {
|
||||
G4Exception("G4MoleculeCounterManager::~G4MoleculeCounterManager", "MOLMAN000", JustWarning,
|
||||
"The molecule counter manager was configured to reset counters before each run"
|
||||
" but the BeginOfRunAction was never triggered!\n"
|
||||
"Ensure that the user code calls either the G4DNAChemistryManager's or "
|
||||
"G4MoleculeCounterManager's Run methods!");
|
||||
}
|
||||
if (GetResetCountersBeforeEvent() && !fBeginOfEventTriggered.load()
|
||||
&& (!G4Threading::IsMultithreadedApplication() || G4Threading::IsWorkerThread()))
|
||||
{
|
||||
// ignore, if this is the master of a MT application
|
||||
G4Exception("G4MoleculeCounterManager::~G4MoleculeCounterManager", "MOLMAN000", JustWarning,
|
||||
"The molecule counter manager was configured to reset counters before each event"
|
||||
" but the BeginOfEventAction was never triggered!\n"
|
||||
"This can occurr if this thread is never processing an event but:\n"
|
||||
"Ensure that the user code calls either the G4DNAChemistryManager's or "
|
||||
"G4MoleculeCounterManager's Event methods!");
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the recorded master and worker instances
|
||||
if (G4Threading::IsMasterThread()) {
|
||||
// This is the master's dtor: set the master const* to nullptr (as it will point to nothing of use)
|
||||
G4AutoLock lockMaster(&masterInstanceMutex);
|
||||
fpMasterInstance = nullptr;
|
||||
}
|
||||
else {
|
||||
// This is a worker's dtor: make sure that this worker is still in the list of instances.
|
||||
// If not, throw a warning (something fishy going on?)
|
||||
// Either way, set this worker's const* to nullptr in the list of instances.
|
||||
G4AutoLock lock(&workerInstancesMutex);
|
||||
auto it = std::find(fWorkerInstances.begin(), fWorkerInstances.end(), this);
|
||||
if (it == fWorkerInstances.end()) {
|
||||
G4Exception(
|
||||
"G4MoleculeCounterManager::~G4MoleculeCounterManager", "MOLMAN_DTOR", JustWarning,
|
||||
"The destroyed instance of G4MoleculeCounterManager has not been registered as a worker!");
|
||||
}
|
||||
else {
|
||||
(*it) = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void G4MoleculeCounterManager::RegisterInstance()
|
||||
{
|
||||
if (fInstancesRegistered) {
|
||||
G4Exception("G4MoleculeCounterManager::RegisterInstance", "MOLMAN000", FatalException,
|
||||
"Instances were already registered once!");
|
||||
}
|
||||
else {
|
||||
if (G4Threading::IsMasterThread()) {
|
||||
G4AutoLock lock(&masterInstanceMutex);
|
||||
if (fpMasterInstance != nullptr) {
|
||||
G4Exception("G4MoleculeCounterManager::RegisterInstance", "MOLMAN000", FatalException,
|
||||
"Master instance was set already!");
|
||||
}
|
||||
fpMasterInstance = Instance();
|
||||
}
|
||||
else {
|
||||
G4AutoLock lock(&workerInstancesMutex);
|
||||
fWorkerInstances.push_back(Instance());
|
||||
}
|
||||
fInstancesRegistered = true;
|
||||
}
|
||||
}
|
||||
|
||||
G4MoleculeCounterManager* G4MoleculeCounterManager::Instance()
|
||||
{
|
||||
if (fpInstance == nullptr) {
|
||||
G4AutoLock lock(&managerInstance);
|
||||
fpInstance = std::make_unique<G4MoleculeCounterManager>(G4MoleculeCounterManager::Private());
|
||||
fpInstance->RegisterInstance();
|
||||
}
|
||||
return fpInstance.get();
|
||||
}
|
||||
|
||||
G4MoleculeCounterManager* G4MoleculeCounterManager::GetInstanceIfExists()
|
||||
{
|
||||
return fpInstance.get();
|
||||
}
|
||||
|
||||
void G4MoleculeCounterManager::DeleteInstance()
|
||||
{
|
||||
G4AutoLock lock(&managerInstance);
|
||||
|
||||
if (fpInstance != nullptr) {
|
||||
fpInstance.reset();
|
||||
// this should (test!) trigger the dtor, which will delete/deregister the counters
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// Initialization
|
||||
//
|
||||
|
||||
void G4MoleculeCounterManager::Initialize()
|
||||
{
|
||||
if (fVerbosity > 0) {
|
||||
G4cout << "G4MoleculeCounterManager::Initialize ("
|
||||
<< (G4Threading::IsMasterThread() ? "master" : "worker") << ")" << G4endl;
|
||||
}
|
||||
|
||||
if (G4Threading::IsMultithreadedApplication()) {
|
||||
if (G4Threading::IsWorkerThread())
|
||||
InitializeWorker();
|
||||
else
|
||||
InitializeMaster();
|
||||
}
|
||||
else {
|
||||
InitializeMaster();
|
||||
}
|
||||
}
|
||||
|
||||
void G4MoleculeCounterManager::InitializeMaster()
|
||||
{
|
||||
if (fIsInitialized) return;
|
||||
for (auto& counter : fCounters)
|
||||
counter.second->Initialize();
|
||||
}
|
||||
|
||||
void G4MoleculeCounterManager::InitializeWorker()
|
||||
{
|
||||
if (fIsInitialized) return;
|
||||
for (auto& counter : fCounters)
|
||||
counter.second->Initialize();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// Add & Remove Molecules
|
||||
//
|
||||
|
||||
void G4MoleculeCounterManager::AddMoleculeWithoutTrack(const G4MolecularConfiguration* molecule,
|
||||
G4double time, G4int n)
|
||||
{
|
||||
for (auto& [id, counter] : fCounters) {
|
||||
counter->AddMolecule(counter->BuildSimpleIndex(molecule), time, n);
|
||||
}
|
||||
}
|
||||
|
||||
void G4MoleculeCounterManager::RemoveMoleculeWithoutTrack(const G4MolecularConfiguration* molecule,
|
||||
G4double time, G4int n)
|
||||
{
|
||||
for (auto& [id, counter] : fCounters) {
|
||||
counter->RemoveMolecule(counter->BuildSimpleIndex(molecule), time, n);
|
||||
}
|
||||
}
|
||||
|
||||
void G4MoleculeCounterManager::AddMolecule(const G4Track* aTrack, G4double time, G4int n)
|
||||
{
|
||||
for (auto& [id, counter] : fCounters) {
|
||||
counter->AddMolecule(counter->BuildIndex(aTrack), time, n);
|
||||
}
|
||||
}
|
||||
|
||||
void G4MoleculeCounterManager::RemoveMolecule(const G4Track* aTrack, G4double time, G4int n)
|
||||
{
|
||||
for (auto& [id, counter] : fCounters) {
|
||||
counter->RemoveMolecule(counter->BuildIndex(aTrack), time, n);
|
||||
}
|
||||
}
|
||||
|
||||
void G4MoleculeCounterManager::AddMolecule(const G4Track* aTrack, const G4StepPoint* aStepPoint,
|
||||
G4double time, G4int n)
|
||||
{
|
||||
for (auto& [id, counter] : fCounters) {
|
||||
if (counter->GetSensitiveToStepping()) {
|
||||
counter->AddMolecule(counter->BuildIndex(aTrack, aStepPoint), time, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void G4MoleculeCounterManager::RemoveMolecule(const G4Track* aTrack, const G4StepPoint* aStepPoint,
|
||||
G4double time, G4int n)
|
||||
{
|
||||
for (auto& [id, counter] : fCounters) {
|
||||
if (counter->GetSensitiveToStepping()) {
|
||||
counter->RemoveMolecule(counter->BuildIndex(aTrack, aStepPoint), time, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
void G4MoleculeCounterManager::RecordReaction(const G4DNAMolecularReactionData* reactionData,
|
||||
G4double time, G4int n)
|
||||
{
|
||||
for (auto& [id, counter] : fReactionCounters) {
|
||||
counter->RecordReaction(counter->BuildSimpleIndex(reactionData), time, n);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// Notification of Step or Finalization (must be implemented in a custom G4ITTrackingInteractivity!
|
||||
//
|
||||
|
||||
/* Example:
|
||||
void ChemistrySteppingAction::UserSteppingAction(const G4Step* aStep)
|
||||
{
|
||||
if (G4MoleculeCounterManager::Instance()->GetIsActive())
|
||||
G4MoleculeCounterManager::Instance()->NotifyOfStep(aStep);
|
||||
}
|
||||
*/
|
||||
|
||||
void G4MoleculeCounterManager::NotifyOfStep(const G4Step* aStep)
|
||||
{
|
||||
const G4Track* aTrack = aStep->GetTrack();
|
||||
|
||||
for (auto& [id, counter] : fCounters) {
|
||||
auto preStepIndex = counter->BuildIndex(aTrack, aStep->GetPreStepPoint());
|
||||
auto postStepIndex = counter->BuildIndex(aTrack, aStep->GetPostStepPoint());
|
||||
|
||||
if (!(*preStepIndex == *postStepIndex)) {
|
||||
#ifdef G4VERBOSE
|
||||
if (GetVerbosity() > 1) {
|
||||
G4cout << "G4MoleculeCounterManager::NotifyOfStep for counter " << counter->GetName()
|
||||
<< ":\n-- Pre = " << preStepIndex->GetInfo() << "\n"
|
||||
<< "-- Post = " << postStepIndex->GetInfo() << G4endl;
|
||||
}
|
||||
#endif
|
||||
counter->RemoveMolecule(std::move(preStepIndex), aTrack->GetGlobalTime(), 1);
|
||||
counter->AddMolecule(std::move(postStepIndex), aTrack->GetGlobalTime(), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void G4MoleculeCounterManager::NotifyOfFinalize()
|
||||
{
|
||||
for (auto& [id, counter] : fCounters) {
|
||||
counter->SchedulerFinalizedTracking();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Broadcast Functions
|
||||
//
|
||||
|
||||
void G4MoleculeCounterManager::BroadcastIgnoreMolecule(const G4MoleculeDefinition* molecule)
|
||||
{
|
||||
for (auto& [id, counter] : fCounters) {
|
||||
counter->IgnoreMolecule(molecule);
|
||||
}
|
||||
}
|
||||
|
||||
void G4MoleculeCounterManager::BroadcastIgnoreReactant(const G4MolecularConfiguration* molecule)
|
||||
{
|
||||
for (auto& [id, counter] : fCounters) {
|
||||
counter->IgnoreReactant(molecule);
|
||||
}
|
||||
}
|
||||
|
||||
void G4MoleculeCounterManager::BroadcastRegisterAllMoleculesAndReactants()
|
||||
{
|
||||
for (auto& [id, counter] : fCounters) {
|
||||
counter->RegisterAll();
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// Manager Functions
|
||||
//
|
||||
|
||||
G4int G4MoleculeCounterManager::RegisterCounter(std::unique_ptr<G4VMoleculeCounter> counter)
|
||||
{
|
||||
auto idProvider = [&]() {
|
||||
if (fCounters.size() == 0) return 0;
|
||||
auto indices = G4::MoleculeCounter::GetMapIndices(fCounters);
|
||||
auto lastIndex = *indices.rbegin();
|
||||
return ++lastIndex;
|
||||
};
|
||||
|
||||
return RegisterCounter(fCounters, std::move(counter), idProvider);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
G4int G4MoleculeCounterManager::RegisterCounter(std::unique_ptr<G4VMoleculeReactionCounter> counter)
|
||||
{
|
||||
auto idProvider = [&] {
|
||||
if (fReactionCounters.size() == 0) return 0;
|
||||
auto indices = G4::MoleculeCounter::GetMapIndices(fReactionCounters);
|
||||
auto lastIndex = *indices.rbegin();
|
||||
return ++lastIndex;
|
||||
};
|
||||
|
||||
return RegisterCounter(fReactionCounters, std::move(counter), idProvider);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4MoleculeCounterManager::DeregisterAllCounters()
|
||||
{
|
||||
for (auto& [id, ctr] : fCounters) {
|
||||
delete ctr;
|
||||
}
|
||||
fCounters.clear();
|
||||
|
||||
for (auto& [id, ctr] : fReactionCounters) {
|
||||
delete ctr;
|
||||
}
|
||||
fReactionCounters.clear();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// Manipulate Counters
|
||||
//
|
||||
|
||||
void G4MoleculeCounterManager::ResetCounters()
|
||||
{
|
||||
if (fVerbosity > 0) {
|
||||
G4cout << "G4MoleculeCounterManager::ResetCounters ("
|
||||
<< (G4Threading::IsMasterThread() ? "master" : "worker") << ")" << G4endl;
|
||||
}
|
||||
|
||||
for (auto& [id, counter] : fCounters)
|
||||
counter->ResetCounter();
|
||||
for (auto& [id, counter] : fReactionCounters)
|
||||
counter->ResetCounter();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4MoleculeCounterManager::ActivateCounterAtTimes(G4int id, G4double aboveTime,
|
||||
G4double belowTime, G4bool aboveTimeInclusive,
|
||||
G4bool belowTimeInclusive)
|
||||
{
|
||||
if (fVerbosity > 0) {
|
||||
G4cout << "G4MoleculeCounterManager::ActivateCounterAtTimes ("
|
||||
<< (G4Threading::IsMasterThread() ? "master" : "worker") << ")" << G4endl;
|
||||
}
|
||||
|
||||
auto counter = GetEditableMoleculeCounter(id);
|
||||
counter->SetActiveLowerBound(aboveTime, aboveTimeInclusive);
|
||||
counter->SetActiveUpperBound(belowTime, belowTimeInclusive);
|
||||
}
|
||||
|
||||
void G4MoleculeCounterManager::ActivateReactionCounterAtTimes(G4int id, G4double aboveTime,
|
||||
G4double belowTime,
|
||||
G4bool aboveTimeInclusive,
|
||||
G4bool belowTimeInclusive)
|
||||
{
|
||||
if (fVerbosity > 0) {
|
||||
G4cout << "G4MoleculeCounterManager::ActivateReactionCounterAtTimes ("
|
||||
<< (G4Threading::IsMasterThread() ? "master" : "worker") << ")" << G4endl;
|
||||
}
|
||||
|
||||
auto counter = GetEditableMoleculeReactionCounter(id);
|
||||
counter->SetActiveLowerBound(aboveTime, aboveTimeInclusive);
|
||||
counter->SetActiveUpperBound(belowTime, belowTimeInclusive);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
G4VMoleculeCounter* G4MoleculeCounterManager::GetEditableMoleculeCounter(G4int id) const
|
||||
{
|
||||
auto it = fCounters.find(id);
|
||||
if (it == fCounters.end()) {
|
||||
G4ExceptionDescription description;
|
||||
description << "No molecule counter with Id = " << id << " was found!\n";
|
||||
G4Exception("G4MoleculeCounterManager::GetMoleculeCounter", "MOLMAN001", FatalErrorInArgument,
|
||||
description);
|
||||
return nullptr;
|
||||
}else{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<const G4VMoleculeCounter*> G4MoleculeCounterManager::GetMoleculeCounters() const
|
||||
{
|
||||
std::vector<const G4VMoleculeCounter*> output;
|
||||
output.reserve(fCounters.size());
|
||||
for (auto& [id, counter] : fCounters)
|
||||
output.push_back(counter);
|
||||
return output;
|
||||
}
|
||||
|
||||
std::vector<const G4VMoleculeCounter*> G4MoleculeCounterManager::GetMoleculeCounters(G4String name) const
|
||||
{
|
||||
std::vector<const G4VMoleculeCounter*> output;
|
||||
for (auto& [id, counter] : fCounters) {
|
||||
if (name == counter->GetName()) output.push_back(counter);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
G4VMoleculeReactionCounter*
|
||||
G4MoleculeCounterManager::GetEditableMoleculeReactionCounter(G4int id) const
|
||||
{
|
||||
auto it = fReactionCounters.find(id);
|
||||
if (it == fReactionCounters.end()) {
|
||||
G4ExceptionDescription description;
|
||||
description << "No molecule reaction counter with Id = " << id << " was found!\n";
|
||||
G4Exception("G4MoleculeCounterManager::GetMoleculeReactionCounter", "MOLMAN001",
|
||||
FatalErrorInArgument, description);
|
||||
return nullptr;
|
||||
}else
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<const G4VMoleculeReactionCounter*>
|
||||
G4MoleculeCounterManager::GetMoleculeReactionCounters() const
|
||||
{
|
||||
std::vector<const G4VMoleculeReactionCounter*> output;
|
||||
output.reserve(fReactionCounters.size());
|
||||
for (auto& [id, counter] : fReactionCounters)
|
||||
output.push_back(counter);
|
||||
return output;
|
||||
}
|
||||
|
||||
std::vector<const G4VMoleculeReactionCounter*>
|
||||
G4MoleculeCounterManager::GetMoleculeReactionCounters(G4String name) const
|
||||
{
|
||||
std::vector<const G4VMoleculeReactionCounter*> output;
|
||||
for (auto& [id, counter] : fReactionCounters) {
|
||||
if (name == counter->GetName()) output.push_back(counter);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4MoleculeCounterManager::BeginOfEventAction(const G4Event*)
|
||||
{
|
||||
fBeginOfEventTriggered = true;
|
||||
|
||||
if (GetResetCountersBeforeEvent()) {
|
||||
// trigger reset if:
|
||||
// * is not an MT app (master = worker)
|
||||
// * is an MT app, master, and we want to reset the master
|
||||
// * is an MT app and worker
|
||||
if (!G4Threading::IsMultithreadedApplication()
|
||||
|| (G4Threading::IsMultithreadedApplication() && G4Threading::IsMasterThread()
|
||||
&& GetResetMasterCounterWithWorkers())
|
||||
|| (G4Threading::IsMultithreadedApplication() && G4Threading::IsWorkerThread()))
|
||||
ResetCounters();
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4MoleculeCounterManager::BeginOfRunAction(const G4Run*)
|
||||
{
|
||||
fBeginOfRunTriggered = true;
|
||||
|
||||
if (GetResetCountersBeforeRun()) {
|
||||
// trigger reset if:
|
||||
// * is not an MT app (master = worker)
|
||||
// * is an MT app, master, and we want to reset the master
|
||||
// * is an MT app and worker
|
||||
if (!G4Threading::IsMultithreadedApplication()
|
||||
|| (G4Threading::IsMultithreadedApplication() && G4Threading::IsMasterThread()
|
||||
&& GetResetMasterCounterWithWorkers())
|
||||
|| (G4Threading::IsMultithreadedApplication() && G4Threading::IsWorkerThread()))
|
||||
ResetCounters();
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4MoleculeCounterManager::EndOfEventAction(const G4Event*)
|
||||
{
|
||||
// EndOfEvent is never triggered on the master of a G4MT
|
||||
if (GetAccumulateCounterIntoMaster() && GetResetCountersBeforeEvent()
|
||||
&& G4Threading::IsMultithreadedApplication() && G4Threading::IsWorkerThread())
|
||||
{
|
||||
AbsorbWorkerManagerCounters(this);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4MoleculeCounterManager::EndOfRunAction(const G4Run*)
|
||||
{
|
||||
if (GetAccumulateCounterIntoMaster() && GetResetCountersBeforeRun()
|
||||
&& !GetResetCountersBeforeEvent() &&
|
||||
// if ResetBeforeEvent, AbsorbWorkerManagerCounters will have been triggered already
|
||||
G4Threading::IsMultithreadedApplication() && G4Threading::IsMasterThread())
|
||||
AbsorbWorkerManagerCounters();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4MoleculeCounterManager::AbsorbWorkerManagerCounters(
|
||||
const G4MoleculeCounterManager* selectedWorker)
|
||||
{
|
||||
if (selectedWorker == nullptr && !G4Threading::IsMasterThread()) {
|
||||
// Can only call without worker from master thread!
|
||||
G4ExceptionDescription description;
|
||||
description << "This method may only be called from the master thread!";
|
||||
G4Exception("G4MoleculeCounterManager::AbsorbWorkerManagerCounters", "MOLMAN999",
|
||||
FatalException, description);
|
||||
}
|
||||
|
||||
// prevent changes to any of the instances
|
||||
G4AutoLock lockMaster(&masterInstanceMutex);
|
||||
G4AutoLock lockWorker(&workerInstancesMutex);
|
||||
|
||||
for (auto const& worker : fWorkerInstances) {
|
||||
if (selectedWorker == nullptr || worker != selectedWorker) continue;
|
||||
|
||||
for (auto& [id, masterCounter] : fpMasterInstance->fCounters) {
|
||||
// acquire worker counter
|
||||
auto workerCounter = worker->GetMoleculeCounter(id);
|
||||
masterCounter->AbsorbCounter(workerCounter);
|
||||
}
|
||||
|
||||
for (auto& [id, masterCounter] : fpMasterInstance->fReactionCounters) {
|
||||
// acquire worker counter
|
||||
auto workerCounter = worker->GetMoleculeReactionCounter(id);
|
||||
masterCounter->AbsorbCounter(workerCounter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4MoleculeCounterManager::DumpMasterCounters() const
|
||||
{
|
||||
G4AutoLock lock(&masterInstanceMutex);
|
||||
|
||||
for (auto const& pCounter : fpMasterInstance->GetMoleculeCounters()) {
|
||||
G4cout << "=========================================================================== \n"
|
||||
<< " >> [MASTER] Dumping Molecule Counter `" << pCounter->GetName() << "`\n"
|
||||
<< G4endl;
|
||||
pCounter->Dump();
|
||||
G4cout << "\n=========================================================================== "
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
for (auto const& pCounter : fpMasterInstance->GetMoleculeReactionCounters()) {
|
||||
G4cout << "=========================================================================== \n"
|
||||
<< " >> [MASTER] Dumping Molecule Reaction Counter `" << pCounter->GetName() << "`\n"
|
||||
<< G4endl;
|
||||
pCounter->Dump();
|
||||
G4cout << "\n=========================================================================== "
|
||||
<< G4endl;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4MoleculeCounterManager::DumpWorkerCounters() const
|
||||
{
|
||||
G4AutoLock lock(&workerInstancesMutex);
|
||||
|
||||
for (auto const& worker : G4MoleculeCounterManager::fWorkerInstances) {
|
||||
for (auto const& pCounter : worker->GetMoleculeCounters()) {
|
||||
G4cout << "=========================================================================== \n"
|
||||
<< " >> [WORKER<" << worker << ">] Dumping Molecule Counter `" << pCounter->GetName()
|
||||
<< "`\n"
|
||||
<< G4endl;
|
||||
pCounter->Dump();
|
||||
G4cout << "\n=========================================================================== "
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
for (auto const& pCounter : worker->GetMoleculeReactionCounters()) {
|
||||
G4cout << "=========================================================================== \n"
|
||||
<< " >> [WORKER<" << worker << ">] Dumping Molecule Reaction Counter `"
|
||||
<< pCounter->GetName() << "`\n"
|
||||
<< G4endl;
|
||||
pCounter->Dump();
|
||||
G4cout << "\n=========================================================================== "
|
||||
<< G4endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
std::atomic<G4bool> G4MoleculeCounterManager::fResetCountersBeforeEvent(false);
|
||||
std::atomic<G4bool> G4MoleculeCounterManager::fResetCountersBeforeRun(false);
|
||||
std::atomic<G4bool> G4MoleculeCounterManager::fAccumulateCounterIntoMaster(true);
|
||||
std::atomic<G4bool> G4MoleculeCounterManager::fResetMasterCounterWithWorkers(false);
|
||||
|
||||
G4bool G4MoleculeCounterManager::GetResetCountersBeforeEvent() const
|
||||
{
|
||||
return fResetCountersBeforeEvent.load();
|
||||
}
|
||||
void G4MoleculeCounterManager::SetResetCountersBeforeEvent(G4bool flag)
|
||||
{
|
||||
if (G4StateManager::GetStateManager()->GetCurrentState() == G4State_PreInit) {
|
||||
fResetCountersBeforeEvent = flag;
|
||||
}
|
||||
else
|
||||
G4Exception("G4DNAChemistryManager::SetResetCountersBeforeEvent", "WRONG_STATE", FatalException,
|
||||
"This flag may only be set during the PreInit state!");
|
||||
}
|
||||
|
||||
G4bool G4MoleculeCounterManager::GetResetCountersBeforeRun() const
|
||||
{
|
||||
return fResetCountersBeforeRun.load();
|
||||
}
|
||||
void G4MoleculeCounterManager::SetResetCountersBeforeRun(G4bool flag)
|
||||
{
|
||||
if (G4StateManager::GetStateManager()->GetCurrentState() == G4State_PreInit)
|
||||
fResetCountersBeforeRun = flag;
|
||||
else
|
||||
G4Exception("G4DNAChemistryManager::SetResetCountersBeforeRun", "WRONG_STATE", FatalException,
|
||||
"This flag may only be set during the PreInit state!");
|
||||
}
|
||||
|
||||
G4bool G4MoleculeCounterManager::GetAccumulateCounterIntoMaster() const
|
||||
{
|
||||
return fAccumulateCounterIntoMaster.load();
|
||||
}
|
||||
void G4MoleculeCounterManager::SetAccumulateCounterIntoMaster(G4bool flag)
|
||||
{
|
||||
if (G4StateManager::GetStateManager()->GetCurrentState() == G4State_PreInit)
|
||||
fAccumulateCounterIntoMaster = flag;
|
||||
else
|
||||
G4Exception("G4DNAChemistryManager::SetAccumulateCounterIntoMaster", "WRONG_STATE",
|
||||
FatalException, "This flag may only be set during the PreInit state!");
|
||||
}
|
||||
|
||||
G4bool G4MoleculeCounterManager::GetResetMasterCounterWithWorkers() const
|
||||
{
|
||||
return fResetMasterCounterWithWorkers.load();
|
||||
}
|
||||
void G4MoleculeCounterManager::SetResetMasterCounterWithWorkers(G4bool flag)
|
||||
{
|
||||
if (G4StateManager::GetStateManager()->GetCurrentState() == G4State_PreInit)
|
||||
fResetMasterCounterWithWorkers = flag;
|
||||
else
|
||||
G4Exception("G4DNAChemistryManager::SetResetMasterCounterWithWorkers", "WRONG_STATE",
|
||||
FatalException, "This flag may only be set during the PreInit state!");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// Author: Christian Velten (2025)
|
||||
|
||||
#include "G4MoleculeCounterManagerMessenger.hh"
|
||||
|
||||
#include "G4MoleculeCounterManager.hh"
|
||||
|
||||
G4MoleculeCounterManagerMessenger::G4MoleculeCounterManagerMessenger(
|
||||
G4MoleculeCounterManager* manager)
|
||||
: G4UImessenger(), fpManager(manager)
|
||||
{
|
||||
fpManagerDir = std::make_unique<G4UIdirectory>("/chem/moleculecounters/", false);
|
||||
fpManagerDir->SetGuidance("Molecule Counter Manager Commands");
|
||||
fpManagerDir->AvailableForStates(G4State_PreInit);
|
||||
|
||||
InitializeCommands();
|
||||
}
|
||||
|
||||
void G4MoleculeCounterManagerMessenger::InitializeCommands()
|
||||
{
|
||||
fpActiveCmd = std::make_unique<G4UIcmdWithABool>("/chem/moleculecounters/active", this);
|
||||
fpActiveCmd->AvailableForStates(G4State_PreInit);
|
||||
|
||||
fpResetBeforeEventCmd =
|
||||
std::make_unique<G4UIcmdWithABool>("/chem/moleculecounters/resetBeforeEvent", this);
|
||||
fpResetBeforeEventCmd->AvailableForStates(G4State_PreInit);
|
||||
|
||||
fpResetBeforeRunCmd =
|
||||
std::make_unique<G4UIcmdWithABool>("/chem/moleculecounters/resetBeforeRun", this);
|
||||
fpResetBeforeRunCmd->AvailableForStates(G4State_PreInit);
|
||||
|
||||
fpAccumulateIntoMasterCmd =
|
||||
std::make_unique<G4UIcmdWithABool>("/chem/moleculecounters/accumulateIntoMaster", this);
|
||||
fpAccumulateIntoMasterCmd->AvailableForStates(G4State_PreInit);
|
||||
|
||||
fpVerboseCmd = std::make_unique<G4UIcmdWithAnInteger>("/chem/moleculecounters/verbose", this);
|
||||
fpVerboseCmd->SetDefaultValue(0);
|
||||
fpVerboseCmd->AvailableForStates(G4State_Idle, G4State_Init, G4State_PreInit, G4State_EventProc,
|
||||
G4State_GeomClosed);
|
||||
}
|
||||
|
||||
void G4MoleculeCounterManagerMessenger::SetNewValue(G4UIcommand* command, G4String newValue)
|
||||
{
|
||||
if (command == fpActiveCmd.get()) {
|
||||
auto value = fpActiveCmd->ConvertToBool(newValue);
|
||||
fpManager->SetIsActive(value);
|
||||
}
|
||||
else if (command == fpResetBeforeEventCmd.get()) {
|
||||
auto value = fpResetBeforeEventCmd->ConvertToBool(newValue);
|
||||
fpManager->SetResetCountersBeforeEvent(value);
|
||||
}
|
||||
else if (command == fpResetBeforeRunCmd.get()) {
|
||||
auto value = fpResetBeforeRunCmd->ConvertToBool(newValue);
|
||||
fpManager->SetResetCountersBeforeRun(value);
|
||||
}
|
||||
else if (command == fpAccumulateIntoMasterCmd.get()) {
|
||||
auto value = fpAccumulateIntoMasterCmd->ConvertToBool(newValue);
|
||||
fpManager->SetAccumulateCounterIntoMaster(value);
|
||||
}
|
||||
else if (command == fpVerboseCmd.get()) {
|
||||
auto value = fpVerboseCmd->ConvertToInt(newValue);
|
||||
fpManager->SetVerbosity(value);
|
||||
}
|
||||
}
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// Author: Christian Velten (2025)
|
||||
|
||||
#include "G4MoleculeCounterTimeComparer.hh"
|
||||
|
||||
#include "G4Exception.hh"
|
||||
|
||||
G4MoleculeCounterTimeComparer::G4MoleculeCounterTimeComparer()
|
||||
: fType(TimeComparerType::FixedPrecision)
|
||||
{}
|
||||
|
||||
G4MoleculeCounterTimeComparer::G4MoleculeCounterTimeComparer(
|
||||
const G4MoleculeCounterTimeComparer& other)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
G4MoleculeCounterTimeComparer&
|
||||
G4MoleculeCounterTimeComparer::operator=(const G4MoleculeCounterTimeComparer& other)
|
||||
{
|
||||
switch (other.fType) {
|
||||
case TimeComparerType::VariablePrecision:
|
||||
SetVariablePrecision(other.fVariablePrecision);
|
||||
break;
|
||||
case TimeComparerType::FixedPrecision:
|
||||
default:
|
||||
SetFixedPrecision(other.fPrecision);
|
||||
break;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void G4MoleculeCounterTimeComparer::SetFixedPrecision(G4double precision)
|
||||
{
|
||||
fType = TimeComparerType::FixedPrecision;
|
||||
fPrecision = precision;
|
||||
}
|
||||
|
||||
void G4MoleculeCounterTimeComparer::SetVariablePrecision(
|
||||
const std::vector<G4double>& globalTimeHighEdges, const std::vector<G4double>& resolutions)
|
||||
{
|
||||
fType = TimeComparerType::VariablePrecision;
|
||||
fVariablePrecision.clear();
|
||||
for (auto key = globalTimeHighEdges.cbegin(), val = resolutions.cbegin();
|
||||
key != globalTimeHighEdges.cend() && val != resolutions.cend(); ++key, ++val)
|
||||
{
|
||||
fVariablePrecision.emplace(*key, *val);
|
||||
}
|
||||
|
||||
if (fVariablePrecision.empty()) {
|
||||
G4Exception("G4MoleculeCounterTimeComparer::SetVariablePrecision()",
|
||||
"G4MoleculeCounterTimeComparer", FatalException, "Precision map cannot be empty!");
|
||||
}
|
||||
}
|
||||
|
||||
void G4MoleculeCounterTimeComparer::SetVariablePrecision(
|
||||
const std::map<G4double, G4double>& resolutionMap)
|
||||
{
|
||||
fType = TimeComparerType::VariablePrecision;
|
||||
fVariablePrecision = resolutionMap;
|
||||
|
||||
if (fVariablePrecision.empty()) {
|
||||
G4Exception("G4MoleculeCounterTimeComparer::SetVariablePrecision()",
|
||||
"G4MoleculeCounterTimeComparer", FatalException, "Precision map cannot be empty!");
|
||||
}
|
||||
}
|
||||
|
||||
G4double G4MoleculeCounterTimeComparer::GetPrecisionAtTime(G4double time) const
|
||||
{
|
||||
if (fType == G4MoleculeCounterTimeComparer::FixedPrecision)
|
||||
return fPrecision;
|
||||
else
|
||||
return fVariablePrecision.upper_bound(time)->second;
|
||||
}
|
||||
|
||||
G4bool G4MoleculeCounterTimeComparer::operator()(const G4double& a, const G4double& b) const
|
||||
{
|
||||
if (fType == G4MoleculeCounterTimeComparer::FixedPrecision) {
|
||||
if (std::fabs(a - b) < fPrecision) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (fType == G4MoleculeCounterTimeComparer::VariablePrecision) {
|
||||
const auto it_a = fVariablePrecision.upper_bound(a);
|
||||
const auto it_b = fVariablePrecision.upper_bound(b);
|
||||
auto precision = fVariablePrecision.crbegin()->second;
|
||||
if (it_a != fVariablePrecision.cend() && it_b != fVariablePrecision.cend())
|
||||
precision = std::min(it_a->second, it_b->second);
|
||||
if (std::fabs(a - b) < precision) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
G4Exception("G4MoleculeCounterTimeComparer::operator()", "G4MoleculeCounterTimeComparer",
|
||||
FatalException, "Unknown comparison type");
|
||||
}
|
||||
return a < b;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
G4MoleculeCounterTimeComparer
|
||||
G4MoleculeCounterTimeComparer::CreateWithFixedPrecision(G4double precision)
|
||||
{
|
||||
auto obj = G4MoleculeCounterTimeComparer();
|
||||
obj.SetFixedPrecision(precision);
|
||||
return obj;
|
||||
}
|
||||
|
||||
G4MoleculeCounterTimeComparer
|
||||
G4MoleculeCounterTimeComparer::CreateWithVariablePrecision(const std::map<G4double, G4double>& map)
|
||||
{
|
||||
auto obj = G4MoleculeCounterTimeComparer();
|
||||
obj.SetVariablePrecision(map);
|
||||
return obj;
|
||||
}
|
||||
+24
-60
@@ -27,82 +27,46 @@
|
||||
// Geant4
|
||||
//
|
||||
// Created by Mathieu Karamitros on 02/11/2016.
|
||||
// Modified by Christian Velten on 10/27/2024.
|
||||
//
|
||||
//
|
||||
|
||||
#include "G4VMoleculeCounter.hh"
|
||||
#include "G4MoleculeCounter.hh"
|
||||
G4ThreadLocal
|
||||
G4VMoleculeCounter* G4VMoleculeCounter::fpInstance = nullptr;
|
||||
|
||||
#include "G4MoleculeCounterTemplates.hh"
|
||||
#include "G4ios.hh"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
G4VMoleculeCounter::SetInstance(G4VMoleculeCounter* pCounterInstance)
|
||||
G4VMoleculeCounter::G4VMoleculeCounter() : G4VMoleculeCounterInternalBase() {}
|
||||
|
||||
G4VMoleculeCounter::G4VMoleculeCounter(const G4String& name, MoleculeCounterType type)
|
||||
: G4VMoleculeCounterInternalBase(name), fType(type)
|
||||
{}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4VMoleculeCounter::SetSensitiveToStepping(G4bool flag)
|
||||
{
|
||||
if (fpInstance != nullptr)
|
||||
{
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "The G4MoleculeCounter was already initialized." << G4endl
|
||||
<< "The previous instance will be deleted in order to use yours." << G4endl
|
||||
<< "However this can generate conflicts. Make sure you call G4MoleculeCounter::SetInstance"
|
||||
"at the beginning of your application."
|
||||
<< "A good place would be ActionInitialization::Build & BuildForMaster"
|
||||
<< G4endl;
|
||||
|
||||
G4Exception("G4MoleculeCounter::SetInstance",
|
||||
"SINGLETON_ALREADY_INITIALIZED",
|
||||
JustWarning, errMsg);
|
||||
delete fpInstance;
|
||||
fpInstance = nullptr;
|
||||
}
|
||||
|
||||
fpInstance = pCounterInstance;
|
||||
if (fType == MoleculeCounterType::Basic && flag) {
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "Cannot set a molecule counter of type 'Basic' to be sensitive to stepping!"
|
||||
<< G4endl;
|
||||
G4Exception("G4VMoleculeCounter::SetSensitiveToStepping", "NOT_ALLOWED", FatalException, errMsg);
|
||||
}
|
||||
fSensitiveToStepping = flag;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
G4VMoleculeCounter* G4VMoleculeCounter::Instance()
|
||||
G4bool G4VMoleculeCounter::IsReactantIgnored(const G4MoleculeDefinition* molecule) const
|
||||
{
|
||||
if (fpInstance == nullptr)
|
||||
{
|
||||
fpInstance = new G4MoleculeCounter();
|
||||
}
|
||||
return fpInstance;
|
||||
return G4::MoleculeCounter::Contains(fIgnoredMolecules, molecule);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4VMoleculeCounter::DeleteInstance()
|
||||
G4bool G4VMoleculeCounter::IsReactantIgnored(const G4MolecularConfiguration* reactant) const
|
||||
{
|
||||
if (fpInstance != nullptr)
|
||||
{
|
||||
delete fpInstance;
|
||||
fpInstance = nullptr;
|
||||
}
|
||||
return G4::MoleculeCounter::Contains(fIgnoredReactants, reactant);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4VMoleculeCounter::InitializeInstance()
|
||||
{
|
||||
if (fpInstance != nullptr)
|
||||
{
|
||||
fpInstance->Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4VMoleculeCounter::Use(G4bool flag)
|
||||
{
|
||||
fUse = flag;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
G4bool G4VMoleculeCounter::InUse()
|
||||
{
|
||||
return fUse;
|
||||
}
|
||||
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// Author: Christian Velten (2025)
|
||||
|
||||
#include "G4VMoleculeCounterInternalBase.hh"
|
||||
|
||||
namespace G4
|
||||
{
|
||||
namespace MoleculeCounter
|
||||
{
|
||||
|
||||
G4bool FixedTimeComparer::operator()(const G4double& a, const G4double& b) const
|
||||
{
|
||||
if (std::fabs(a - b) < fPrecision) {
|
||||
return false;
|
||||
}
|
||||
return a < b;
|
||||
}
|
||||
|
||||
G4ThreadLocal G4double FixedTimeComparer::fPrecision = 0.1 * picosecond;
|
||||
} // namespace MoleculeCounter
|
||||
} // namespace G4
|
||||
|
||||
G4ThreadLocal G4int G4VMoleculeCounterInternalBase::_createdCounters = 0;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
G4VMoleculeCounterInternalBase::G4VMoleculeCounterInternalBase() : fId(_createdCounters++) {}
|
||||
|
||||
G4VMoleculeCounterInternalBase::G4VMoleculeCounterInternalBase(const G4String& name)
|
||||
: fId(_createdCounters++), fName(name)
|
||||
{}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4VMoleculeCounterInternalBase::SetFixedTimePrecision(G4double precision)
|
||||
{
|
||||
G4::MoleculeCounter::FixedTimeComparer::fPrecision = precision;
|
||||
}
|
||||
+8
-20
@@ -23,29 +23,17 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
/*
|
||||
# <<BEGIN-copyright>>
|
||||
# <<END-copyright>>
|
||||
*/
|
||||
#ifndef G4GIDI_map_h_included
|
||||
#define G4GIDI_map_h_included 1
|
||||
// Author: Christian Velten (2025)
|
||||
|
||||
#include <string>
|
||||
//using namespace std;
|
||||
#include "G4VMoleculeReactionCounter.hh"
|
||||
|
||||
#include <MCGIDI_map.h>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class G4GIDI_map {
|
||||
G4VMoleculeReactionCounter::G4VMoleculeReactionCounter() : G4VMoleculeCounterInternalBase() {}
|
||||
|
||||
public:
|
||||
GIDI::statusMessageReporting smr;
|
||||
GIDI::MCGIDI_map *map;
|
||||
G4VMoleculeReactionCounter::G4VMoleculeReactionCounter(const G4String& name, MoleculeReactionCounterType type)
|
||||
: G4VMoleculeCounterInternalBase(name), fType(type)
|
||||
{}
|
||||
|
||||
G4GIDI_map( const std::string &dataDirectory );
|
||||
~G4GIDI_map( );
|
||||
|
||||
std::string path( void );
|
||||
std::string fileName( void );
|
||||
};
|
||||
|
||||
#endif // End of G4GIDI_map_h_included
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,92 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
|
||||
#ifndef TRANSPORTATION_H
|
||||
#define TRANSPORTATION_H
|
||||
|
||||
#include "G4DNABoundingBox.hh"
|
||||
#include "G4ITReaction.hh"
|
||||
#include "G4ITTransportation.hh"
|
||||
#include "G4MolecularConfiguration.hh"
|
||||
|
||||
class G4Molecule;
|
||||
class G4VUserBrownianAction;
|
||||
|
||||
class G4ChemReboundTransportation : public G4ITTransportation
|
||||
{
|
||||
using MolConf = const G4MolecularConfiguration*;
|
||||
|
||||
public:
|
||||
explicit G4ChemReboundTransportation(const G4String& aName = "ChemReboundTransportation",
|
||||
const G4DNABoundingBox* = nullptr, G4int verbosityLevel = 0);
|
||||
~G4ChemReboundTransportation() override = default;
|
||||
G4ChemReboundTransportation(const G4ChemReboundTransportation&) = delete;
|
||||
G4ChemReboundTransportation& operator=(const G4ChemReboundTransportation&) = delete;
|
||||
void BuildPhysicsTable(const G4ParticleDefinition&) override;
|
||||
void StartTracking(G4Track* aTrack) override;
|
||||
void ComputeStep(const G4Track&, const G4Step&, G4double, G4double&) override;
|
||||
G4double AlongStepGetPhysicalInteractionLength(const G4Track& /*track*/,
|
||||
G4double /*previousStepSize*/,
|
||||
G4double /*currentMinimumStep*/,
|
||||
G4double& /*currentSafety*/,
|
||||
G4GPILSelection* /*selection*/) override;
|
||||
|
||||
G4VParticleChange* PostStepDoIt(const G4Track& track, const G4Step&) override;
|
||||
G4VParticleChange* AlongStepDoIt(const G4Track& track, const G4Step&) override;
|
||||
|
||||
inline void SetBoundary(const G4DNABoundingBox*);
|
||||
static G4double calculateNextCoordinate(G4double nextPos, G4double high, G4double low);
|
||||
G4double GetTimeToBoundary(const G4Track& track);
|
||||
|
||||
protected:
|
||||
//________________________________________________________________
|
||||
// Process information
|
||||
struct G4ITBrownianState : public G4ITTransportationState
|
||||
{
|
||||
public:
|
||||
G4ITBrownianState();
|
||||
~G4ITBrownianState() override = default;
|
||||
G4String GetType() override { return "Rebound"; }
|
||||
|
||||
G4bool fTimeStepReachedLimit;
|
||||
G4double fRandomNumber;
|
||||
};
|
||||
G4ITReactionSet* fReactionSet = G4ITReactionSet::Instance();
|
||||
|
||||
G4Material* fNistWater = nullptr;
|
||||
G4double fMaximumTimeStep = 0;
|
||||
G4double fInternalMinTimeStep;
|
||||
const G4DNABoundingBox* fpBoundingBox = nullptr;
|
||||
G4ThreeVector BouncingAction(const G4ThreeVector& nextPosition);
|
||||
G4double calculateDistanceFromTimeStep(MolConf mol, G4double timeStep);
|
||||
};
|
||||
|
||||
inline void G4ChemReboundTransportation::SetBoundary(const G4DNABoundingBox* pBounding)
|
||||
{
|
||||
fpBoundingBox = pBounding;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -28,6 +28,8 @@
|
||||
#define G4DNASCAVENGERPROCESS_HH
|
||||
|
||||
#include "G4VITProcess.hh"
|
||||
#include "G4MoleculeTable.hh"
|
||||
|
||||
class G4DNAMolecularReactionData;
|
||||
class G4MolecularConfiguration;
|
||||
class G4DNABoundingBox;
|
||||
@@ -100,5 +102,8 @@ class G4DNAScavengerProcess : public G4VITProcess
|
||||
MolType fpMaterialConf;
|
||||
const G4DNABoundingBox* fpBoundingBox;
|
||||
G4DNAScavengerMaterial* fpScavengerMaterial{nullptr};
|
||||
MolType fH3Op = G4MoleculeTable::Instance()->GetConfiguration("H3Op(B)");
|
||||
MolType fH2O = G4MoleculeTable::Instance()->GetConfiguration("H2O");
|
||||
MolType fHOm = G4MoleculeTable::Instance()->GetConfiguration("OHm(B)");
|
||||
};
|
||||
#endif // FLASH1_G4DNASCAVENGERPROCESS_HH
|
||||
|
||||
@@ -26,6 +26,7 @@ geant4_add_module(G4emdna-processes
|
||||
G4DNADoubleIonisation.hh
|
||||
G4DNATripleIonisation.hh
|
||||
G4DNAQuadrupleIonisation.hh
|
||||
G4ChemReboundTransportation.hh
|
||||
SOURCES
|
||||
G4DNAAttachment.cc
|
||||
G4DNABrownianTransportation.cc
|
||||
@@ -48,7 +49,8 @@ geant4_add_module(G4emdna-processes
|
||||
G4DNAPolyNucleotideReactionProcess.cc
|
||||
G4DNADoubleIonisation.cc
|
||||
G4DNATripleIonisation.cc
|
||||
G4DNAQuadrupleIonisation.cc)
|
||||
G4DNAQuadrupleIonisation.cc
|
||||
G4ChemReboundTransportation.cc)
|
||||
|
||||
geant4_module_link_libraries(G4emdna-processes
|
||||
PUBLIC
|
||||
|
||||
@@ -0,0 +1,404 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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 "G4ChemReboundTransportation.hh"
|
||||
|
||||
#include "G4DNAMolecularMaterial.hh"
|
||||
#include "G4H3O.hh"
|
||||
#include "G4ITNavigator.hh"
|
||||
#include "G4ITSafetyHelper.hh" // Not used yet
|
||||
#include "G4LowEnergyEmProcessSubType.hh"
|
||||
#include "G4Molecule.hh"
|
||||
#include "G4NistManager.hh"
|
||||
#include "G4ParticleTable.hh"
|
||||
#include "G4RandomDirection.hh"
|
||||
#include "G4SafetyHelper.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4TrackingInformation.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
#include "G4VUserBrownianAction.hh"
|
||||
#include "Randomize.hh"
|
||||
|
||||
#include <CLHEP/Random/Stat.h>
|
||||
using namespace std;
|
||||
|
||||
#ifndef State
|
||||
# define State(theXInfo) (GetState<G4ITBrownianState>()->theXInfo)
|
||||
#endif
|
||||
|
||||
static G4double InvErfc(G4double x)
|
||||
{
|
||||
return CLHEP::HepStat::inverseErf(1. - x);
|
||||
}
|
||||
|
||||
#ifndef State
|
||||
# define State(theXInfo) (GetState<G4ITTransportationState>()->theXInfo)
|
||||
#endif
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4ChemReboundTransportation::G4ChemReboundTransportation(const G4String& aName,
|
||||
const G4DNABoundingBox* pB,
|
||||
G4int verbosity)
|
||||
: G4ITTransportation(aName, verbosity), fpBoundingBox(pB)
|
||||
{
|
||||
fVerboseLevel = 0;
|
||||
fpState = std::make_shared<G4ITBrownianState>();
|
||||
SetProcessSubType(fLowEnergyBrownianTransportation);
|
||||
fNistWater = G4NistManager::Instance()->FindOrBuildMaterial("G4_WATER");
|
||||
fInternalMinTimeStep = 1 * CLHEP::ps;
|
||||
}
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4ChemReboundTransportation::G4ITBrownianState::G4ITBrownianState()
|
||||
{
|
||||
fTimeStepReachedLimit = false;
|
||||
fRandomNumber = -1;
|
||||
}
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4ChemReboundTransportation::StartTracking(G4Track* track)
|
||||
{
|
||||
fpState = std::make_shared<G4ITBrownianState>();
|
||||
SetInstantiateProcessState(false);
|
||||
G4ITTransportation::StartTracking(track);
|
||||
}
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4ChemReboundTransportation::BuildPhysicsTable(const G4ParticleDefinition& particle)
|
||||
{
|
||||
fpSafetyHelper->InitialiseHelper();
|
||||
G4ITTransportation::BuildPhysicsTable(particle);
|
||||
|
||||
if (fpBoundingBox == nullptr) {
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "fpBoundingBox is nullptr";
|
||||
G4Exception(
|
||||
"ChemReboundTransportation::BuildPhysicsTable"
|
||||
"ChemReboundTransportation",
|
||||
"ChemReboundTransportation", FatalErrorInArgument, errMsg);
|
||||
}
|
||||
G4double halfSize =
|
||||
std::min({fpBoundingBox->halfSideLengthInX(), fpBoundingBox->halfSideLengthInY(),
|
||||
fpBoundingBox->halfSideLengthInZ()});
|
||||
fMaximumTimeStep = (halfSize * halfSize) / (60 * G4H3O::Definition()->GetDiffusionCoefficient());
|
||||
}
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4ChemReboundTransportation::ComputeStep(const G4Track& track, const G4Step& step,
|
||||
const G4double timeStep, G4double& spaceStep)
|
||||
{
|
||||
if (GetIT(track)->GetTrackingInfo()->IsLeadingStep()) {
|
||||
G4ExceptionDescription exceptionDescription;
|
||||
exceptionDescription << "ComputeStep is called while the track has"
|
||||
"the minimum interaction time";
|
||||
exceptionDescription << " so it should not recompute a timeStep ";
|
||||
G4Exception("ChemReboundTransportation::ComputeStep", "ChemReboundTransportation0001",
|
||||
FatalErrorInArgument, exceptionDescription);
|
||||
}
|
||||
State(fGeometryLimitedStep) = false;
|
||||
if (timeStep == 0) {
|
||||
State(fTransportEndPosition) = track.GetPosition();
|
||||
spaceStep = 0.;
|
||||
}
|
||||
else {
|
||||
auto molConf = GetMolecule(track)->GetMolecularConfiguration();
|
||||
spaceStep = calculateDistanceFromTimeStep(molConf, timeStep);
|
||||
}
|
||||
State(fTransportEndPosition) =
|
||||
BouncingAction(track.GetPosition() + spaceStep * G4RandomDirection());
|
||||
State(fEndPointDistance) = (track.GetPosition() - State(fTransportEndPosition)).mag();
|
||||
if (fVerboseLevel > 1)
|
||||
// if(GetMolecule(track)->GetName() == "e_aq^-1")
|
||||
{
|
||||
G4cout << G4endl;
|
||||
G4cout << "ComputeStep: timeStep : " << G4BestUnit(timeStep, "Time")
|
||||
<< " State(theInteractionTimeLeft) : " << State(theInteractionTimeLeft)
|
||||
<< " State(fEndPointDistance) : " << G4BestUnit(State(fEndPointDistance), "Length")
|
||||
<< " trackID : " << track.GetTrackID()
|
||||
<< " Molecule name: " << "track.GetPosition() : " << track.GetPosition()
|
||||
<< " State(fTransportEndPosition) : " << State(fTransportEndPosition) << " "
|
||||
<< GetMolecule(track)->GetName() << " Diffusion length : " << G4endl;
|
||||
}
|
||||
State(fCandidateEndGlobalTime) = step.GetPreStepPoint()->GetGlobalTime() + timeStep;
|
||||
State(fEndGlobalTimeComputed) = true;
|
||||
}
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4VParticleChange* G4ChemReboundTransportation::PostStepDoIt(const G4Track& track,
|
||||
const G4Step& step)
|
||||
{
|
||||
G4ITTransportation::PostStepDoIt(track, step);
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
// DEBUG
|
||||
if (fVerboseLevel > 1)
|
||||
// if(GetMolecule(track)->GetName() == "e_aq^-1")
|
||||
if (GetIT(track)->GetTrackingInfo()->IsLeadingStep()) {
|
||||
G4cout << "ChemReboundTransportation::PostStepDoIt() :" << " trackID : " << track.GetTrackID()
|
||||
<< " Molecule name: " << "prePosition : " << step.GetPreStepPoint()->GetPosition()
|
||||
<< " postPostion : " << step.GetPostStepPoint()->GetPosition() << " "
|
||||
<< GetMolecule(track)->GetName()
|
||||
<< " Diffusion length : " << G4BestUnit(step.GetStepLength(), "Length")
|
||||
<< " within time step : " << G4BestUnit(step.GetDeltaTime(), "Time")
|
||||
<< "\t Current global time : " << G4BestUnit(track.GetGlobalTime(), "Time")
|
||||
<< " track.GetMomentumDirection() : " << track.GetMomentumDirection() << G4endl;
|
||||
}
|
||||
#endif
|
||||
return &fParticleChange;
|
||||
}
|
||||
|
||||
G4double G4ChemReboundTransportation::AlongStepGetPhysicalInteractionLength(
|
||||
const G4Track& track, G4double /*previousStepSize*/, G4double /*currentMinimumStep*/,
|
||||
G4double& /*currentSafety*/, G4GPILSelection* /*selection*/)
|
||||
{
|
||||
if (!fpBoundingBox->contains(track.GetPosition())) {
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "Point is out of box : " << *fpBoundingBox
|
||||
<< " of particle : " << GetIT(track)->GetName() << "(" << track.GetTrackID()
|
||||
<< ") : " << track.GetPosition();
|
||||
G4Exception(
|
||||
"ChemReboundTransportation::AlongStepGetPhysicalInteractionLength"
|
||||
"ChemReboundTransportation",
|
||||
"ChemReboundTransportation", FatalErrorInArgument, errMsg);
|
||||
}
|
||||
if (fNistWater != track.GetMaterial()) {
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "This is not water";
|
||||
G4Exception(
|
||||
"ChemReboundTransportation::AlongStepGetPhysicalInteractionLength"
|
||||
"ChemReboundTransportation",
|
||||
"ChemReboundTransportation", FatalErrorInArgument, errMsg);
|
||||
}
|
||||
|
||||
G4double geometryStepLength = DBL_MAX;
|
||||
State(theInteractionTimeLeft) = DBL_MAX;
|
||||
|
||||
auto molConf = GetMolecule(track)->GetMolecularConfiguration();
|
||||
G4ITReactionPerTime& reactionPerTime = fReactionSet->GetReactionsPerTime();
|
||||
auto reaction_i = reactionPerTime.begin();
|
||||
if (reaction_i == reactionPerTime.end()) {
|
||||
State(fGeometryLimitedStep) = false;
|
||||
State(theInteractionTimeLeft) = fMaximumTimeStep;
|
||||
if (fVerboseLevel > 1) {
|
||||
G4cout << "out of reaction " << G4BestUnit(State(theInteractionTimeLeft), "Time") << G4endl;
|
||||
}
|
||||
}
|
||||
else {
|
||||
G4Track* pTrackA = (*reaction_i)->GetReactants().first;
|
||||
G4Track* pTrackB = (*reaction_i)->GetReactant(pTrackA);
|
||||
|
||||
if (&track == pTrackA || &track == pTrackB) {
|
||||
State(theInteractionTimeLeft) = GetTimeToBoundary(track);
|
||||
State(fTimeStepReachedLimit) = false;
|
||||
State(fGeometryLimitedStep) = false;
|
||||
|
||||
if (fVerboseLevel > 1)
|
||||
G4cout << "Molecule A is of type : " << GetMolecule(track)->GetName()
|
||||
<< " with trackID : " << track.GetTrackID()
|
||||
<< " fMaximumTimeStep : " << G4BestUnit(fMaximumTimeStep, "Time")
|
||||
<< " State(theInteractionTimeLeft) : "
|
||||
<< G4BestUnit(State(theInteractionTimeLeft), "Time") << G4endl;
|
||||
|
||||
if (State(theInteractionTimeLeft) < fInternalMinTimeStep) {
|
||||
State(fTimeStepReachedLimit) = true;
|
||||
State(theInteractionTimeLeft) = fInternalMinTimeStep;
|
||||
}
|
||||
else if (State(theInteractionTimeLeft) > fMaximumTimeStep) {
|
||||
State(fTimeStepReachedLimit) = true;
|
||||
State(theInteractionTimeLeft) = fMaximumTimeStep;
|
||||
}
|
||||
}
|
||||
else {
|
||||
State(fGeometryLimitedStep) = false;
|
||||
State(theInteractionTimeLeft) = DBL_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
geometryStepLength = calculateDistanceFromTimeStep(molConf, State(theInteractionTimeLeft));
|
||||
State(fTransportEndPosition) =
|
||||
geometryStepLength * track.GetMomentumDirection() + track.GetPosition();
|
||||
State(fTimeStepReachedLimit) = true;
|
||||
State(fCandidateEndGlobalTime) = track.GetGlobalTime() + State(theInteractionTimeLeft);
|
||||
State(fEndGlobalTimeComputed) = true;
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if (fVerboseLevel > 1) {
|
||||
G4cout << "ChemReboundTransportation::AlongStepGetPhysicalInteractionLength = "
|
||||
<< G4BestUnit(geometryStepLength, "Length") << " "
|
||||
<< G4BestUnit(State(theInteractionTimeLeft), "Time")
|
||||
<< " | trackID = " << track.GetTrackID() << G4endl;
|
||||
}
|
||||
#endif
|
||||
return geometryStepLength;
|
||||
}
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4VParticleChange* G4ChemReboundTransportation::AlongStepDoIt(const G4Track& track,
|
||||
const G4Step& step)
|
||||
{
|
||||
if (GetIT(track)->GetTrackingInfo()->IsLeadingStep()) {
|
||||
G4double spaceStep = DBL_MAX;
|
||||
auto molConf = GetMolecule(track)->GetMolecularConfiguration();
|
||||
spaceStep = calculateDistanceFromTimeStep(molConf, State(theInteractionTimeLeft));
|
||||
|
||||
State(fGeometryLimitedStep) = false;
|
||||
State(fTransportEndPosition) =
|
||||
BouncingAction(track.GetPosition() + spaceStep * G4RandomDirection());
|
||||
State(fEndPointDistance) = spaceStep;
|
||||
if (fVerboseLevel > 1)
|
||||
// if(GetMolecule(track)->GetName() == "e_aq^-1")
|
||||
|
||||
{
|
||||
G4cout << "ChemReboundTransportation::AlongStepDoIt() :" << " trackID : "
|
||||
<< track.GetTrackID()
|
||||
<< " Molecule name: " << "prePosition : " << step.GetPreStepPoint()->GetPosition()
|
||||
<< " postPostion : " << step.GetPostStepPoint()->GetPosition() << " "
|
||||
<< GetMolecule(track)->GetName() << " State(theInteractionTimeLeft) : "
|
||||
<< G4BestUnit(State(theInteractionTimeLeft), "Time")
|
||||
<< " Diffusion length : " << G4BestUnit(step.GetStepLength(), "Length")
|
||||
<< " within time step : " << G4BestUnit(step.GetDeltaTime(), "Time")
|
||||
<< "\t Current global time : " << G4BestUnit(track.GetGlobalTime(), "Time")
|
||||
<< " track.GetMomentumDirection() : " << track.GetMomentumDirection() << G4endl;
|
||||
}
|
||||
}
|
||||
|
||||
G4ITTransportation::AlongStepDoIt(track, step);
|
||||
|
||||
return &fParticleChange;
|
||||
}
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4ThreeVector G4ChemReboundTransportation::BouncingAction(const G4ThreeVector& nextPosition)
|
||||
{
|
||||
// from Karamitros, Mathieu et al.2020,arXiv:2006.14225 (2020)
|
||||
// https://doi.org/10.48550/arXiv.2006.14225
|
||||
|
||||
G4ThreeVector output;
|
||||
|
||||
G4double RxM = fpBoundingBox->Getxhi();
|
||||
G4double RyM = fpBoundingBox->Getyhi();
|
||||
G4double RzM = fpBoundingBox->Getzhi();
|
||||
G4double Rxm = fpBoundingBox->Getxlo();
|
||||
G4double Rym = fpBoundingBox->Getylo();
|
||||
G4double Rzm = fpBoundingBox->Getzlo();
|
||||
|
||||
G4double x = calculateNextCoordinate(nextPosition.getX(), RxM, Rxm);
|
||||
G4double y = calculateNextCoordinate(nextPosition.getY(), RyM, Rym);
|
||||
G4double z = calculateNextCoordinate(nextPosition.getZ(), RzM, Rzm);
|
||||
output.set(x, y, z);
|
||||
return output;
|
||||
}
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4ChemReboundTransportation::calculateNextCoordinate(G4double nextPos, G4double high,
|
||||
G4double low)
|
||||
{
|
||||
// from Karamitros, Mathieu et al.2020,arXiv:2006.14225 (2020)
|
||||
|
||||
G4double length = high - low;
|
||||
if (std::abs(length) < 1e-10) {
|
||||
return low;
|
||||
}
|
||||
|
||||
G4double relativePos = std::abs(nextPos - low);
|
||||
if (!std::isfinite(relativePos)) {
|
||||
return low; // no crash
|
||||
}
|
||||
|
||||
G4double n = relativePos / length;
|
||||
if (!std::isfinite(n)) {
|
||||
return low;
|
||||
}
|
||||
|
||||
G4double truncVal = std::floor(n);//n is already positive
|
||||
G4double h = truncVal;
|
||||
if(truncVal > 2.0){
|
||||
h = std::fmod(truncVal, 2.0);
|
||||
}
|
||||
|
||||
G4double mod = relativePos;
|
||||
|
||||
if(relativePos > length) {
|
||||
mod = std::fmod(relativePos, length);
|
||||
}
|
||||
|
||||
return low + h * length + (1 - 2 * h) * std::abs(mod);
|
||||
}
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4ChemReboundTransportation::calculateDistanceFromTimeStep(MolConf mol, G4double timeStep)
|
||||
{
|
||||
G4double diffuCoeff = mol->GetDiffusionCoefficient();
|
||||
if (mol->GetDiffusionCoefficient() <= 0) {
|
||||
G4ExceptionDescription exceptionDescription;
|
||||
exceptionDescription << "GetDiffusionCoefficient is negative";
|
||||
G4Exception("ChemReboundTransportation::calculateDistanceFromTimeStep",
|
||||
"ChemReboundTransportation030", FatalErrorInArgument, exceptionDescription);
|
||||
}
|
||||
G4double sqrt_2Dt = sqrt(2 * diffuCoeff * timeStep);
|
||||
G4double x = G4RandGauss::shoot(0, sqrt_2Dt);
|
||||
G4double y = G4RandGauss::shoot(0, sqrt_2Dt);
|
||||
G4double z = G4RandGauss::shoot(0, sqrt_2Dt);
|
||||
return sqrt(x * x + y * y + z * z);
|
||||
}
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4ChemReboundTransportation::GetTimeToBoundary(const G4Track& track)
|
||||
{
|
||||
if (!fpBoundingBox->contains(track.GetPosition())) {
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "Point is out of box : " << *fpBoundingBox
|
||||
<< " of particle : " << GetIT(track)->GetName() << "(" << track.GetTrackID()
|
||||
<< ") : " << track.GetPosition();
|
||||
G4Exception(
|
||||
"BoundedBrownianAction::GetTimeToBoundary"
|
||||
"BoundedBrownianAction",
|
||||
"BoundedBrownianAction", FatalErrorInArgument, errMsg);
|
||||
}
|
||||
auto diffusionCoefficient = GetMolecule(track)->GetDiffusionCoefficient();
|
||||
|
||||
auto dx = std::min(track.GetPosition().getX() - fpBoundingBox->Getxlo(),
|
||||
fpBoundingBox->Getxhi() - track.GetPosition().getX());
|
||||
auto dy = std::min(track.GetPosition().getY() - fpBoundingBox->Getylo(),
|
||||
fpBoundingBox->Getyhi() - track.GetPosition().getY());
|
||||
auto dz = std::min(track.GetPosition().getZ() - fpBoundingBox->Getzlo(),
|
||||
fpBoundingBox->Getzhi() - track.GetPosition().getZ());
|
||||
|
||||
std::vector<G4double> distanceVector{dx, dy, dz};
|
||||
G4double MinTime = DBL_MAX;
|
||||
for (const auto& it : distanceVector) {
|
||||
G4double distance = it;
|
||||
auto random = G4UniformRand();
|
||||
auto minTime = 1 / (4 * diffusionCoefficient) * pow(distance / InvErfc(random), 2);
|
||||
|
||||
if (MinTime > minTime) {
|
||||
MinTime = minTime;
|
||||
}
|
||||
}
|
||||
return MinTime;
|
||||
}
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
+7
-11
@@ -44,7 +44,7 @@
|
||||
#include "G4MoleculeFinder.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4VMoleculeCounter.hh"
|
||||
#include "G4MoleculeCounterManager.hh"
|
||||
|
||||
#include <memory>
|
||||
|
||||
@@ -182,21 +182,17 @@ void G4DNAElectronHoleRecombination::MakeReaction(const G4Track& track)
|
||||
|
||||
if (pSelectedReactant != nullptr)
|
||||
{
|
||||
if (G4VMoleculeCounter::Instance()->InUse())
|
||||
if (G4MoleculeCounterManager::Instance()->GetIsActive())
|
||||
{
|
||||
G4VMoleculeCounter::Instance()->
|
||||
RemoveAMoleculeAtTime(GetMolecule(track)->GetMolecularConfiguration(),
|
||||
track.GetGlobalTime(),
|
||||
&(track.GetPosition()));
|
||||
G4MoleculeCounterManager::Instance()->
|
||||
RemoveMolecule(&track, track.GetGlobalTime());
|
||||
}
|
||||
GetMolecule(track)->ChangeConfigurationToLabel("H2Ovib");
|
||||
|
||||
if (G4VMoleculeCounter::Instance()->InUse())
|
||||
if (G4MoleculeCounterManager::Instance()->GetIsActive())
|
||||
{
|
||||
G4VMoleculeCounter::Instance()->
|
||||
AddAMoleculeAtTime(GetMolecule(track)->GetMolecularConfiguration(),
|
||||
track.GetGlobalTime(),
|
||||
&(track.GetPosition()));
|
||||
G4MoleculeCounterManager::Instance()->
|
||||
AddMolecule(&track, track.GetGlobalTime());
|
||||
}
|
||||
|
||||
// fParticleChange.ProposeTrackStatus(fStopAndKill);
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include <G4VScheduler.hh>
|
||||
#include <memory>
|
||||
#include "G4Molecule.hh"
|
||||
#include "G4DNAMolecularMaterial.hh"
|
||||
#include "G4MolecularConfiguration.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
#include "G4TrackingInformation.hh"
|
||||
@@ -38,6 +37,7 @@
|
||||
#include "G4DNAScavengerMaterial.hh"
|
||||
#include "G4MoleculeFinder.hh"
|
||||
#include "G4Scheduler.hh"
|
||||
#include "G4ChemicalMoleculeFinder.hh"
|
||||
|
||||
#ifndef State
|
||||
# define State(theXInfo) (GetState<G4DNAScavengerProcessState>()->theXInfo)
|
||||
@@ -124,10 +124,6 @@ G4double G4DNAScavengerProcess::PostStepGetPhysicalInteractionLength(
|
||||
{
|
||||
G4Molecule* molecule = GetMolecule(track);
|
||||
auto molConf = molecule->GetMolecularConfiguration();
|
||||
// reset
|
||||
fpMolecularConfiguration = nullptr;
|
||||
fpMaterialConf = nullptr;
|
||||
|
||||
// this because process for moleculeDifinition not for configuration
|
||||
// TODO: need change this
|
||||
auto it = fConfMap.find(molConf);
|
||||
@@ -135,6 +131,8 @@ G4double G4DNAScavengerProcess::PostStepGetPhysicalInteractionLength(
|
||||
{
|
||||
return DBL_MAX;
|
||||
}
|
||||
fpMolecularConfiguration = nullptr;
|
||||
fpMaterialConf = nullptr;
|
||||
|
||||
fpMolecularConfiguration = molConf;
|
||||
auto MaterialMap = it->second;
|
||||
@@ -150,20 +148,24 @@ G4double G4DNAScavengerProcess::PostStepGetPhysicalInteractionLength(
|
||||
G4double numMol =
|
||||
fpScavengerMaterial->GetNumberMoleculePerVolumeUnitForMaterialConf(
|
||||
matConf);
|
||||
if(numMol == 0.0) // ie : not found
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if(verboseLevel > 1)
|
||||
{
|
||||
G4cout << " Material of " << matConf->GetName() << " : " << numMol
|
||||
<< G4endl;
|
||||
}
|
||||
// auto data = fReactionMap[mat_it];
|
||||
if(numMol == 0 && matConf != fH2O){
|
||||
continue;}
|
||||
auto data = mat_it.second;
|
||||
auto reactionRate = data->GetObservedReactionRateConstant(); //_const
|
||||
G4double propensity =
|
||||
numMol * reactionRate / (fpBoundingBox->Volume() * Avogadro);
|
||||
|
||||
if(fH2O == matConf){
|
||||
auto factor = reactionRate;
|
||||
propensity = factor;
|
||||
}
|
||||
|
||||
if(verboseLevel > 1)
|
||||
{
|
||||
G4cout << " Material of " << matConf->GetName() << " : " << propensity
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
auto reactionData = std::make_pair(mat_it.first, propensity);
|
||||
if(propensity == 0)
|
||||
{
|
||||
@@ -185,6 +187,13 @@ G4double G4DNAScavengerProcess::PostStepGetPhysicalInteractionLength(
|
||||
|
||||
fpMaterialConf = rSelectedIter->second.first;
|
||||
|
||||
|
||||
auto type = fConfMap[fpMolecularConfiguration][fpMaterialConf]->GetReactionType();
|
||||
if(!fpScavengerMaterial->IsEquilibrium(type))
|
||||
{
|
||||
return DBL_MAX;
|
||||
}
|
||||
|
||||
State(fIsInGoodMaterial) = true;
|
||||
G4double previousTimeStep(-1.);
|
||||
|
||||
@@ -219,12 +228,6 @@ G4double G4DNAScavengerProcess::PostStepGetPhysicalInteractionLength(
|
||||
#ifdef G4VERBOSE
|
||||
if(verboseLevel > 2)
|
||||
{
|
||||
G4cout << "G4DNAScavengerProcess::PostStepGetPhysicalInteractionLength:: "
|
||||
<< molConf->GetName() << G4endl;
|
||||
G4cout << "theNumberOfInteractionLengthLeft : "
|
||||
<< fpState->theNumberOfInteractionLengthLeft << G4endl;
|
||||
G4cout << "currentInteractionLength : " << fpState->currentInteractionLength
|
||||
<< G4endl;
|
||||
G4cout << "Material : " << fpMaterialConf->GetName()
|
||||
<< " ID: " << track.GetTrackID()
|
||||
<< " Track Time : " << track.GetGlobalTime()
|
||||
@@ -249,50 +252,51 @@ G4VParticleChange* G4DNAScavengerProcess::PostStepDoIt(const G4Track& track,
|
||||
{
|
||||
G4Molecule* molecule = GetMolecule(track);
|
||||
auto molConf = molecule->GetMolecularConfiguration();
|
||||
if(fpMolecularConfiguration != molConf)
|
||||
{
|
||||
fReturnedValue = DBL_MAX;
|
||||
fParticleChange.Initialize(track);
|
||||
State(fPreviousTimeAtPreStepPoint) = -1;
|
||||
return &fParticleChange;
|
||||
}
|
||||
std::vector<G4Track*> products;
|
||||
#ifdef G4VERBOSE
|
||||
if(verboseLevel > 1)
|
||||
{
|
||||
G4cout << "___________" << G4endl;
|
||||
G4cout << ">>> Beginning of G4DNAScavengerProcess verbose" << G4endl;
|
||||
G4cout << ">>> Returned value : " << G4BestUnit(fReturnedValue, "Time")
|
||||
<< G4endl;
|
||||
G4cout << ">>> Time Step : "
|
||||
<< G4BestUnit(G4VScheduler::Instance()->GetTimeStep(), "Time")
|
||||
<< G4endl;
|
||||
G4cout << ">>> Global Time : "
|
||||
<< G4BestUnit(G4VScheduler::Instance()->GetGlobalTime(), "Time")
|
||||
<< G4endl;
|
||||
G4cout << ">>> Global Time Track : "
|
||||
<< G4BestUnit(track.GetGlobalTime(), "Time") << G4endl;
|
||||
G4cout << ">>> Track Position : " << track.GetPosition() << G4endl;
|
||||
G4cout << ">>> Reaction : " << molecule->GetName() << "("
|
||||
<< track.GetTrackID() << ") + " << fpMaterialConf->GetName()
|
||||
<< G4endl;
|
||||
G4cout << ">>> End of G4DNAScavengerProcess verbose <<<" << G4endl;
|
||||
G4cout << ">>> Beginning of G4DNAScavengerProcess verbose>>> Returned value : " << G4BestUnit(fReturnedValue, "Time")
|
||||
<<"molecule: "<<molConf->GetName()<<G4endl;
|
||||
G4cout<<" selected Mat : "<<fpMaterialConf->GetName()<< G4endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
G4double reactionTime = track.GetGlobalTime();
|
||||
auto data = fConfMap[fpMolecularConfiguration][fpMaterialConf];
|
||||
auto data = fConfMap[molConf][fpMaterialConf];
|
||||
|
||||
if(data == nullptr)
|
||||
{
|
||||
G4ExceptionDescription exceptionDescription;
|
||||
exceptionDescription
|
||||
<< "No reaction data for scavenger reaction between : "<<fpMaterialConf->GetName()
|
||||
<<" + "<<molConf->GetName()<<G4endl;
|
||||
G4Exception("G4DNAScavengerProcess::PostStepDoIt",
|
||||
"G4DNAScavengerProcess0001111", FatalErrorInArgument,
|
||||
exceptionDescription);
|
||||
}
|
||||
|
||||
fpScavengerMaterial->SetEquilibrium(data, track.GetGlobalTime());
|
||||
|
||||
auto nbSecondaries = data->GetNbProducts();
|
||||
|
||||
for(G4int j = 0; j < nbSecondaries; ++j)
|
||||
{
|
||||
auto product = data->GetProduct(j);
|
||||
auto isScavenger = fpScavengerMaterial->find(product);
|
||||
if(isScavenger){
|
||||
fpScavengerMaterial->
|
||||
AddNumberMoleculePerVolumeUnitForMaterialConf(product,track.GetGlobalTime());
|
||||
continue;
|
||||
}
|
||||
auto pProduct = new G4Molecule(data->GetProduct(j));
|
||||
auto pProductTrack =
|
||||
pProduct->BuildTrack(reactionTime, track.GetPosition());
|
||||
pProductTrack->SetTrackStatus(fAlive);
|
||||
G4ITTrackHolder::Instance()->Push(pProductTrack);
|
||||
G4MoleculeFinder::Instance()->Push(pProductTrack);
|
||||
if(!G4ChemicalMoleculeFinder::Instance()->IsOctreeUsed()){
|
||||
G4MoleculeFinder::Instance()->Push(pProductTrack);
|
||||
}
|
||||
products.push_back(pProductTrack);
|
||||
}
|
||||
|
||||
@@ -318,8 +322,28 @@ G4VParticleChange* G4DNAScavengerProcess::PostStepDoIt(const G4Track& track,
|
||||
|
||||
if(verboseLevel != 0)
|
||||
{
|
||||
G4cout << GetIT(products.at(i))->GetName() << " ("
|
||||
<< products.at(i)->GetTrackID() << ")";
|
||||
auto product = data->GetProduct(i);
|
||||
auto isScavenger = fpScavengerMaterial->find(product);
|
||||
if(isScavenger)
|
||||
{
|
||||
G4cout<<product->GetName()<<" (B)";
|
||||
}
|
||||
else
|
||||
{
|
||||
auto trackSize = products.size();
|
||||
if(trackSize > 0)
|
||||
{
|
||||
for(G4int it = 0; it < (G4int)trackSize; ++it)
|
||||
{
|
||||
if((verboseLevel != 0) && it != 0)
|
||||
{
|
||||
G4cout << " + ";
|
||||
}
|
||||
G4cout << GetIT(products.at(it))->GetName() << " ("
|
||||
<< products.at(it)->GetTrackID() << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -346,5 +370,12 @@ G4VParticleChange* G4DNAScavengerProcess::PostStepDoIt(const G4Track& track,
|
||||
fpScavengerMaterial->ReduceNumberMoleculePerVolumeUnitForMaterialConf(
|
||||
fpMaterialConf, reactionTime);
|
||||
State(fPreviousTimeAtPreStepPoint) = -1;
|
||||
|
||||
if(fpMaterialConf == fH3Op
|
||||
|| fpMaterialConf == fH2O
|
||||
|| fpMaterialConf == fHOm) { // these scavengers are not changed
|
||||
G4Scheduler::Instance()->SetInteractionStep(false);
|
||||
}
|
||||
|
||||
return &fParticleChange;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,10 @@
|
||||
#include "G4UImessenger.hh"
|
||||
#include "G4VStateDependent.hh"
|
||||
|
||||
#include "G4MoleculeCounterManager.hh"
|
||||
|
||||
class G4Track;
|
||||
class G4Run;
|
||||
class G4DNAWaterExcitationStructure;
|
||||
class G4DNAWaterIonisationStructure;
|
||||
class G4Molecule;
|
||||
@@ -150,9 +153,6 @@ public:
|
||||
* in standalone.
|
||||
*/
|
||||
void UseAsStandalone(G4bool flag);
|
||||
G4bool IsCounterResetWhenRunEnds() const;
|
||||
|
||||
void ResetCounterWhenRunEnds(G4bool resetCounterWhenRunEnds);
|
||||
|
||||
void ForceMasterReinitialization();
|
||||
void TagThreadForReinitialization();
|
||||
@@ -199,8 +199,17 @@ public:
|
||||
|
||||
void PushMolecule(std::unique_ptr<G4Molecule> pMolecule,
|
||||
G4double time,
|
||||
const G4ThreeVector& position,
|
||||
G4int parentID);
|
||||
const G4ThreeVector &position,
|
||||
G4int parentID,
|
||||
const G4Track *parentTrack = nullptr);
|
||||
|
||||
//============================================================================
|
||||
// Methods called by RunManagers to notify of Runs & Events
|
||||
//============================================================================
|
||||
void BeginOfEventAction(const G4Event*);
|
||||
void BeginOfRunAction(const G4Run*);
|
||||
void EndOfEventAction(const G4Event*);
|
||||
void EndOfRunAction(const G4Run*);
|
||||
|
||||
protected:
|
||||
void HandleStandaloneInitialization();
|
||||
@@ -251,5 +260,4 @@ private:
|
||||
G4bool fGeometryClosed{false};
|
||||
|
||||
G4int fVerbose{0};
|
||||
G4bool fResetCounterWhenRunEnds{true};
|
||||
};
|
||||
|
||||
@@ -53,6 +53,7 @@ class G4DNAMesh : public G4VDNAMesh
|
||||
Voxel& GetVoxel(const Index& index); // GetorCreateVoxel
|
||||
size_t size() { return fVoxelVector.size(); };
|
||||
Index ConvertIndex(const Index& index, const G4int&) const;
|
||||
Index GetRandomIndex(const Index&, const G4double& resolution) const;
|
||||
std::vector<Index> FindNeighboringVoxels(const Index& index) const;
|
||||
void Reset();
|
||||
Data& GetVoxelMapList(const Index& index);
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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 25.03.2025 V.Ivanchenko
|
||||
// on base of codes of S.Incerti & M.Karamitros
|
||||
//
|
||||
// Double differential cross section data structure
|
||||
//
|
||||
|
||||
#ifndef G4DNASamplingTable_HH
|
||||
#define G4DNASamplingTable_HH 1
|
||||
|
||||
#include "globals.hh"
|
||||
#include <vector>
|
||||
|
||||
class G4DNASamplingTable
|
||||
{
|
||||
public:
|
||||
explicit G4DNASamplingTable(std::size_t npoint);
|
||||
~G4DNASamplingTable();
|
||||
|
||||
void LoadData(const G4String& filename, G4double factorE, G4double scaleFactor,
|
||||
G4bool verbose);
|
||||
|
||||
G4double GetValue(G4double ekinPrimary, G4double ekinSecondary, G4int shell) const;
|
||||
|
||||
G4double SampleCumulative(G4double ekinPrimary, G4int shell) const;
|
||||
|
||||
G4DNASamplingTable(const G4DNASamplingTable & copy) = delete;
|
||||
G4DNASamplingTable& operator=(const G4DNASamplingTable& right) = delete;
|
||||
|
||||
private:
|
||||
|
||||
G4int GetIndex(const std::vector<G4double>&, G4double x) const;
|
||||
|
||||
G4double VecInterpolation(const std::vector<G4double>* ener,
|
||||
const std::vector<G4double>* val, G4double energy) const;
|
||||
|
||||
G4double Interpolate(G4double e1, G4double e2, G4double e,
|
||||
G4double xs1, G4double xs2) const;
|
||||
|
||||
G4int fNpoints{0};
|
||||
std::vector<G4double> fPrimaryEnergy;
|
||||
std::vector<std::vector<G4double>* > fSecEnergy;
|
||||
std::vector<std::vector<G4double>* > fPDF[5];
|
||||
|
||||
};
|
||||
#endif
|
||||
@@ -30,9 +30,10 @@
|
||||
#include "G4ios.hh"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "G4MoleculeCounter.hh"
|
||||
#include "G4VMoleculeCounterInternalBase.hh"
|
||||
#include "G4VScavengerMaterial.hh"
|
||||
#include "G4MoleculeTable.hh"
|
||||
#include "G4ChemEquilibrium.hh"
|
||||
|
||||
class G4Material;
|
||||
class G4MolecularConfiguration;
|
||||
@@ -42,7 +43,7 @@ class G4DNAScavengerMaterial : public G4VScavengerMaterial
|
||||
{
|
||||
public:
|
||||
using NbMoleculeInTime =
|
||||
std::map<G4double, int64_t, G4::MoleculeCounter::TimePrecision>;
|
||||
std::map<G4double, int64_t, G4::MoleculeCounter::FixedTimeComparer>;
|
||||
using MolType = const G4MolecularConfiguration*;
|
||||
using MaterialMap = std::map<MolType, int64_t>;
|
||||
using ReactantList = std::vector<MolType>;
|
||||
@@ -80,9 +81,7 @@ class G4DNAScavengerMaterial : public G4VScavengerMaterial
|
||||
{
|
||||
return it->second > 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
void SetCounterAgainstTime() { fCounterAgainstTime = true; }
|
||||
@@ -103,9 +102,13 @@ class G4DNAScavengerMaterial : public G4VScavengerMaterial
|
||||
int64_t GetNMoleculesAtTime(MolType molecule, G4double time);
|
||||
G4bool SearchTimeMap(MolType molecule);
|
||||
int64_t SearchUpperBoundTime(G4double time, G4bool sameTypeOfMolecule);
|
||||
void ResetEquilibrium();
|
||||
G4bool SetEquilibrium(const G4DNAMolecularReactionData* pReaction,
|
||||
G4double time);
|
||||
G4bool IsEquilibrium(const G4int& reactionType) const;
|
||||
|
||||
private:
|
||||
G4VChemistryWorld* fpChemistryInfo;
|
||||
private:
|
||||
G4VChemistryWorld* fpChemistryInfo = nullptr;
|
||||
G4bool fIsInitialized;
|
||||
MaterialMap fScavengerTable;
|
||||
CounterMapType fCounterMap;
|
||||
@@ -125,5 +128,6 @@ class G4DNAScavengerMaterial : public G4VScavengerMaterial
|
||||
std::unique_ptr<Search> fpLastSearch;
|
||||
void WaterEquilibrium();
|
||||
|
||||
std::map<G4int,std::unique_ptr<G4ChemEquilibrium>> fEquilibriumProcesses;
|
||||
};
|
||||
#endif // G4DNASCAVENGERMATERIAL_HH
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// Author: Christian Velten (2025)
|
||||
|
||||
#ifndef G4MoleculeReactionCounter_hh
|
||||
#define G4MoleculeReactionCounter_hh 1
|
||||
|
||||
#include "G4DNAMolecularReactionTable.hh"
|
||||
#include "G4VUserMoleculeReactionCounter.hh"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
struct G4MoleculeReactionCounterIndex : public G4VMoleculeReactionCounter::G4VMoleculeReactionCounterIndex
|
||||
{
|
||||
const G4DNAMolecularReactionData* ReactionData;
|
||||
|
||||
G4MoleculeReactionCounterIndex() : ReactionData(nullptr) {}
|
||||
explicit G4MoleculeReactionCounterIndex(const G4DNAMolecularReactionData* reaction) : ReactionData(reaction) {}
|
||||
~G4MoleculeReactionCounterIndex() override = default;
|
||||
|
||||
G4bool operator<(G4VMoleculeReactionCounterIndex const& other) const override
|
||||
{
|
||||
return std::less{}(ReactionData, static_cast<const G4MoleculeReactionCounterIndex&>(other).ReactionData);
|
||||
}
|
||||
G4bool operator==(G4VMoleculeReactionCounterIndex const& other) const override
|
||||
{
|
||||
return std::equal_to{}(ReactionData, static_cast<const G4MoleculeReactionCounterIndex&>(other).ReactionData);
|
||||
}
|
||||
G4String FormattedReactionString(const G4DNAMolecularReactionData* reactionData) const;
|
||||
|
||||
G4String GetInfo() const override
|
||||
{
|
||||
G4String null = "This reaction data is null";
|
||||
if (ReactionData == nullptr)
|
||||
return null;
|
||||
else
|
||||
return FormattedReactionString(ReactionData);
|
||||
}
|
||||
const G4DNAMolecularReactionData* GetReactionData() const override { return ReactionData; }
|
||||
};
|
||||
|
||||
class G4MoleculeReactionCounter : public G4VUserMoleculeReactionCounter<G4MoleculeReactionCounterIndex>
|
||||
{
|
||||
//----------------------------------------------------------------------------
|
||||
public:
|
||||
G4MoleculeReactionCounter();
|
||||
G4MoleculeReactionCounter(G4String);
|
||||
~G4MoleculeReactionCounter() override = default;
|
||||
|
||||
void InitializeUser() override;
|
||||
|
||||
public:
|
||||
std::unique_ptr<G4VMoleculeReactionCounterIndex> BuildSimpleIndex(const G4DNAMolecularReactionData*) const override;
|
||||
};
|
||||
|
||||
#endif // G4MoleculeReactionCounter_hh
|
||||
@@ -97,64 +97,6 @@ protected:
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class G4Analysis: public G4VPhysChemIO
|
||||
{
|
||||
public:
|
||||
G4Analysis(G4VAnalysisManager*);
|
||||
~G4Analysis() override;
|
||||
|
||||
void InitializeMaster() override{}
|
||||
void InitializeThread() override{}
|
||||
void InitializeFile() override;
|
||||
|
||||
void NewRun() override{}
|
||||
void NewEvent() override{}
|
||||
|
||||
/**
|
||||
* Method used by DNA physics model to create a water molecule.
|
||||
* The ElectronicModification is a flag telling wheter the molecule
|
||||
* is ionized or excited, the electronic level is calculated by the
|
||||
* model and the IncomingTrack is the track responsible for the creation
|
||||
* of this molecule, for instance an electron.
|
||||
*/
|
||||
void CreateWaterMolecule(G4int electronicModif,
|
||||
G4int /*electronicLevel*/,
|
||||
G4double energy,
|
||||
const G4Track* /*theIncomingTrack*/) override;
|
||||
|
||||
/**
|
||||
* Same idea as the previous method but for solvated electron.
|
||||
* This method should be used by the physics model of the ElectronSolvatation
|
||||
* process.
|
||||
*/
|
||||
void CreateSolvatedElectron(const G4Track* /*theIncomingTrack*/,
|
||||
G4ThreeVector* finalPosition = nullptr) override;
|
||||
|
||||
//============================================================================
|
||||
// FILE OPERATIONS
|
||||
//============================================================================
|
||||
|
||||
/**
|
||||
* Tells the chemMan to write into a file
|
||||
* the position and electronic state of the water molecule
|
||||
* and the position thermalized or not of the solvated electron
|
||||
*/
|
||||
void WriteInto(const G4String&, std::ios_base::openmode mode =
|
||||
std::ios_base::out) override;
|
||||
void AddEmptyLineInOutputFile() override{}
|
||||
|
||||
/**
|
||||
* Close the file specified with WriteInto
|
||||
*/
|
||||
void CloseFile() override;
|
||||
|
||||
protected:
|
||||
G4VAnalysisManager* fpAnalysisManager;
|
||||
int fNtupleID;
|
||||
G4bool fFileInitialized;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // G4PHYSCHEMIO_HH_
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include "globals.hh"
|
||||
class G4DNABoundingBox;
|
||||
class G4Material;
|
||||
class G4MolecularConfiguration;
|
||||
@@ -72,9 +73,14 @@ class G4VChemistryWorld
|
||||
{
|
||||
return fpChemistryBoundary.get();
|
||||
}
|
||||
|
||||
std::map<MolType,G4double> GetChemicalComponent() const
|
||||
{
|
||||
return fpChemicalComponent;
|
||||
}
|
||||
protected:
|
||||
std::unique_ptr<G4DNABoundingBox> fpChemistryBoundary;
|
||||
std::map<MolType,double> fpChemicalComponent;
|
||||
std::map<MolType,G4double> fpChemicalComponent;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,437 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// Author: Christian Velten (2025)
|
||||
|
||||
#ifndef G4VUSERMOLECULEREACTIONCOUNTER_HH
|
||||
#define G4VUSERMOLECULEREACTIONCOUNTER_HH 1
|
||||
|
||||
#include "G4DNAChemistryManager.hh"
|
||||
#include "G4MoleculeCounterTemplates.hh"
|
||||
#include "G4Scheduler.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
#include "G4VMoleculeReactionCounter.hh"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class TIndex>
|
||||
class G4VUserMoleculeReactionCounter : public G4VMoleculeReactionCounter
|
||||
{
|
||||
static_assert(std::is_base_of<G4VMoleculeReactionCounter::G4VMoleculeReactionCounterIndex, TIndex>::value,
|
||||
"TIndex must be derived from G4VMoleculeReactionCounter::G4VMoleculeReactionCounterIndex! "
|
||||
"No forward declaration is allowed.");
|
||||
|
||||
protected:
|
||||
struct Search;
|
||||
|
||||
public:
|
||||
G4VUserMoleculeReactionCounter();
|
||||
G4VUserMoleculeReactionCounter(const G4String&,
|
||||
MoleculeReactionCounterType = MoleculeReactionCounterType::Basic);
|
||||
~G4VUserMoleculeReactionCounter() override = default;
|
||||
|
||||
public:
|
||||
void Initialize() final;
|
||||
void InitializeUser() override = 0;
|
||||
void ResetCounter() override;
|
||||
void Dump() const override;
|
||||
void DumpCounterMapIndices() const override;
|
||||
|
||||
void AbsorbCounter(const G4VMoleculeCounterInternalBase*) override;
|
||||
|
||||
std::unique_ptr<G4VMoleculeReactionCounterIndex> BuildSimpleIndex(const G4DNAMolecularReactionData*) const override = 0;
|
||||
|
||||
void RecordReaction(std::unique_ptr<G4VMoleculeReactionCounterIndex>, G4double, G4int = 1) override;
|
||||
|
||||
std::set<const G4DNAMolecularReactionData*> GetRecordedReactions() const override;
|
||||
std::set<G4double> GetRecordedTimes() const override;
|
||||
|
||||
protected:
|
||||
std::map<TIndex, InnerCounterMapType> fCounterMap{};
|
||||
|
||||
public:
|
||||
const std::map<TIndex, InnerCounterMapType>& GetCounterMap() const { return fCounterMap; }
|
||||
std::vector<TIndex> GetMapIndices() const;
|
||||
|
||||
virtual G4int GetNbReactionsAtTime(const TIndex&, G4double) const;
|
||||
virtual G4int GetNbReactionsAtTime(Search&, const TIndex&, G4double) const;
|
||||
virtual std::vector<G4int> GetNbReactionsAtTimes(const TIndex&,
|
||||
const std::vector<G4double>&) const;
|
||||
|
||||
//-SEARCH-----------------------------------------------------------------------
|
||||
protected:
|
||||
struct Search
|
||||
{
|
||||
Search() : fLowerBoundSet(false) {}
|
||||
typename std::map<TIndex, InnerCounterMapType>::const_iterator fLastIndexSearched;
|
||||
InnerCounterMapType::const_iterator fLowerBoundTime;
|
||||
G4bool fLowerBoundSet;
|
||||
};
|
||||
G4bool SearchIndexUpdated(Search&, const TIndex&) const;
|
||||
G4int SearchUpperBoundTime(Search&, G4double, G4bool) const;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// #include "G4VUserMoleculeReactionCounter.icc"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
G4VUserMoleculeReactionCounter<T>::G4VUserMoleculeReactionCounter() : G4VMoleculeReactionCounter()
|
||||
{}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
G4VUserMoleculeReactionCounter<T>::G4VUserMoleculeReactionCounter(const G4String& name,
|
||||
MoleculeReactionCounterType type)
|
||||
: G4VMoleculeReactionCounter(name, type)
|
||||
{}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename TIndex>
|
||||
void G4VUserMoleculeReactionCounter<TIndex>::Initialize()
|
||||
{
|
||||
InitializeUser();
|
||||
fIsInitialized = true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename TIndex>
|
||||
G4int G4VUserMoleculeReactionCounter<TIndex>::GetNbReactionsAtTime(const TIndex& index, G4double time) const
|
||||
{
|
||||
Search search = {};
|
||||
return GetNbReactionsAtTime(search, index, time);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename TIndex>
|
||||
G4int G4VUserMoleculeReactionCounter<TIndex>::GetNbReactionsAtTime(Search& search,
|
||||
const TIndex& index,
|
||||
G4double time) const
|
||||
{
|
||||
G4bool sameIndex = !SearchIndexUpdated(search, index);
|
||||
return SearchUpperBoundTime(search, time, sameIndex);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename TIndex>
|
||||
std::vector<G4int> G4VUserMoleculeReactionCounter<TIndex>::GetNbReactionsAtTimes(
|
||||
const TIndex& index, const std::vector<G4double>& times) const
|
||||
{
|
||||
Search search = {};
|
||||
std::vector<G4int> counts = {};
|
||||
for (auto time : times)
|
||||
counts.push_back(GetNbReactionsAtTime(search, index, time));
|
||||
return counts;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename TIndex>
|
||||
void G4VUserMoleculeReactionCounter<TIndex>::RecordReaction(
|
||||
std::unique_ptr<G4VMoleculeReactionCounter::G4VMoleculeReactionCounterIndex> pIndex,
|
||||
G4double time, G4int number)
|
||||
{
|
||||
const TIndex* mapIndex = dynamic_cast<TIndex*>(pIndex.get());
|
||||
|
||||
if (IsTimeAboveUpperBound(time)) {
|
||||
if (fVerbose > 3) {
|
||||
G4cout << "G4VUserMoleculeReactionCounter<"
|
||||
<< G4::MoleculeCounter::GetTemplateTypeName<TIndex>() << ">(" << GetName()
|
||||
<< ")::RecordReaction : " << mapIndex->GetReactionData()->GetReactionID()
|
||||
<< " at time : " << G4BestUnit(time, "Time") << G4endl;
|
||||
G4cout << ":: [IsTimeAboveUpperBound] Skipping since IsTimeAboveUpperBound == true" << G4endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (IsTimeBelowLowerBound(time)) {
|
||||
if (fVerbose > 3) {
|
||||
G4cout << "G4VUserMoleculeReactionCounter<"
|
||||
<< G4::MoleculeCounter::GetTemplateTypeName<TIndex>() << ">(" << GetName()
|
||||
<< ")::RecordReaction : " << mapIndex->GetReactionData()->GetReactionID()
|
||||
<< " at time : " << G4BestUnit(time, "Time") << G4endl;
|
||||
G4cout << ":: [IsTimeBelowLowerBound] Skipping since IsTimeBelowLowerBound == true" << G4endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (fVerbose > 2) {
|
||||
G4cout << "G4VUserMoleculeReactionCounter<"
|
||||
<< G4::MoleculeCounter::GetTemplateTypeName<TIndex>() << ">(" << GetName()
|
||||
<< ")::RecordReaction : " << mapIndex->GetReactionData()->GetReactionID()
|
||||
<< " at time : " << G4BestUnit(time, "Time") << G4endl;
|
||||
}
|
||||
|
||||
auto [it, indexIsNew] = fCounterMap.emplace(*mapIndex, InnerCounterMapType{fTimeComparer});
|
||||
|
||||
if (indexIsNew || it->second.empty()) {
|
||||
it->second.emplace(time, number);
|
||||
// it->second[time] = number;
|
||||
}
|
||||
else {
|
||||
if (G4MoleculeCounterManager::Instance()->GetResetCountersBeforeEvent())
|
||||
// can only do consistency check if the counters are cleared before each event
|
||||
{
|
||||
auto end = it->second.rbegin();
|
||||
|
||||
if ((end->first <= time || std::fabs(end->first - time) <= fTimeComparer.GetPrecisionAtTime(time)))
|
||||
// Case 1 = new time comes after last recorded data
|
||||
// Case 2 = new time is about the same as the last recorded one
|
||||
{
|
||||
// it->second[time] = end->second + number;
|
||||
auto [it_time, _] = it->second.emplace(time, end->second);
|
||||
it_time->second += number;
|
||||
}
|
||||
else {
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "Time of reaction " << mapIndex->GetReactionData()->GetReactionID() << " is "
|
||||
<< G4BestUnit(time, "Time") << "while the global time is "
|
||||
<< G4BestUnit(G4Scheduler::Instance()->GetGlobalTime(), "Time")
|
||||
<< "(last counter time: " << G4BestUnit(end->first, "Time") << ")" << G4endl;
|
||||
G4Exception(G4String("G4VUserMoleculeReactionCounter<"
|
||||
+ G4::MoleculeCounter::GetTemplateTypeName<TIndex>()
|
||||
+ ">::RecordReaction"),
|
||||
"TIME_DONT_MATCH", FatalException, errMsg);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// since counters are not cleared after chemical run (i.e., after event)
|
||||
// there will already be numbers in the map, so...
|
||||
// (1) find the closest time
|
||||
// (2) emplace entry using closest value as init + number
|
||||
// (3) add number to all "future" entries as well
|
||||
auto it_closest = G4::MoleculeCounter::FindClosestEntryForKey(it->second, time);
|
||||
auto [it_new, _] = it->second.emplace(time, it_closest->second);
|
||||
do {
|
||||
it_new->second += number;
|
||||
} while (++it_new != it->second.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename TIndex>
|
||||
std::vector<TIndex> G4VUserMoleculeReactionCounter<TIndex>::GetMapIndices() const
|
||||
{
|
||||
if (fVerbose > 2) {
|
||||
G4cout << "Entering in G4VUserMoleculeReactionCounter::GetMapIndices" << G4endl;
|
||||
}
|
||||
return G4::MoleculeCounter::GetMapIndices(fCounterMap);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
std::set<const G4DNAMolecularReactionData*> G4VUserMoleculeReactionCounter<T>::GetRecordedReactions() const
|
||||
{
|
||||
if (fVerbose > 2) {
|
||||
G4cout << "Entering in G4VUserMoleculeReactionCounter::GetRecordedReactions" << G4endl;
|
||||
}
|
||||
std::set<const G4DNAMolecularReactionData*> output{};
|
||||
for (const auto& it : fCounterMap) {
|
||||
output.insert(it.first.GetReactionData());
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
std::set<G4double> G4VUserMoleculeReactionCounter<T>::GetRecordedTimes() const
|
||||
{
|
||||
return G4::MoleculeCounter::GetRecordedTimes<T>(fCounterMap);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
void G4VUserMoleculeReactionCounter<T>::Dump() const
|
||||
{
|
||||
DumpCounterMapIndices();
|
||||
G4::MoleculeCounter::DumpCounterMapContents<T>(fCounterMap);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void G4VUserMoleculeReactionCounter<T>::DumpCounterMapIndices() const
|
||||
{
|
||||
G4::MoleculeCounter::DumpCounterMapIndices<T>(fCounterMap);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
void G4VUserMoleculeReactionCounter<T>::ResetCounter()
|
||||
{
|
||||
if (fVerbose > 1) {
|
||||
G4cout << "G4VUserMoleculeReactionCounter<" << G4::MoleculeCounter::GetTemplateTypeName<T>()
|
||||
<< ">(" << GetName() << ")::ResetCounter" << G4endl;
|
||||
}
|
||||
fCounterMap.clear();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename TIndex>
|
||||
G4bool G4VUserMoleculeReactionCounter<TIndex>::SearchIndexUpdated(Search& search, const TIndex& index) const
|
||||
{
|
||||
if (search.fLowerBoundSet && !(search.fLastIndexSearched->first < index)
|
||||
&& !(index < search.fLastIndexSearched->first))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
auto mol_it = fCounterMap.find(index);
|
||||
search.fLastIndexSearched = mol_it;
|
||||
|
||||
if (mol_it != fCounterMap.end()) {
|
||||
search.fLowerBoundTime = search.fLastIndexSearched->second.end();
|
||||
search.fLowerBoundSet = true;
|
||||
}
|
||||
else {
|
||||
search.fLowerBoundSet = false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
G4int G4VUserMoleculeReactionCounter<T>::SearchUpperBoundTime(Search& search, G4double time, G4bool sameIndex) const
|
||||
{
|
||||
auto mol_it = search.fLastIndexSearched;
|
||||
if (mol_it == fCounterMap.end()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
InnerCounterMapType const& timeMap = mol_it->second;
|
||||
if (timeMap.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sameIndex) {
|
||||
if (search.fLowerBoundSet && search.fLowerBoundTime != timeMap.end()) {
|
||||
if (search.fLowerBoundTime->first < time) {
|
||||
auto upperToLast = search.fLowerBoundTime;
|
||||
upperToLast++;
|
||||
|
||||
if (upperToLast == timeMap.end()) {
|
||||
return search.fLowerBoundTime->second;
|
||||
}
|
||||
|
||||
if (upperToLast->first > time) {
|
||||
return search.fLowerBoundTime->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto up_time_it = timeMap.upper_bound(time);
|
||||
|
||||
if (up_time_it == timeMap.end()) {
|
||||
auto last_time = timeMap.rbegin();
|
||||
return last_time->second;
|
||||
}
|
||||
if (up_time_it == timeMap.begin()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
up_time_it--;
|
||||
|
||||
search.fLowerBoundTime = up_time_it;
|
||||
search.fLowerBoundSet = true;
|
||||
|
||||
return search.fLowerBoundTime->second;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<typename TIndex>
|
||||
void G4VUserMoleculeReactionCounter<TIndex>::AbsorbCounter(
|
||||
const G4VMoleculeCounterInternalBase* pCounterBase)
|
||||
{
|
||||
if (pCounterBase == nullptr) {
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "Could not cast the pointer to type G4VUserMoleculeReactionCounter<"
|
||||
<< G4::MoleculeCounter::GetTemplateTypeName<TIndex>() << ">!\n"
|
||||
<< "Because the pointer is nullptr!" << G4endl;
|
||||
G4Exception(G4String("G4VUserMoleculeReactionCounter<"
|
||||
+ G4::MoleculeCounter::GetTemplateTypeName<TIndex>() + ">::AbsorbCounter"),
|
||||
"BAD_REFERENCE", FatalException, errMsg);
|
||||
}
|
||||
|
||||
auto pCounter = dynamic_cast<G4VUserMoleculeReactionCounter<TIndex> const*>(pCounterBase);
|
||||
|
||||
if (pCounter == nullptr) {
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "Could not cast the pointer to type G4VUserMoleculeReactionCounter<"
|
||||
<< G4::MoleculeCounter::GetTemplateTypeName<TIndex>() << ">!\n"
|
||||
<< "Because the objects aren't of the same type!" << G4endl;
|
||||
G4Exception(G4String("G4VUserMoleculeReactionCounter<"
|
||||
+ G4::MoleculeCounter::GetTemplateTypeName<TIndex>() + ">::AbsorbCounter"),
|
||||
"BAD_REFERENCE", FatalException, errMsg);
|
||||
}
|
||||
|
||||
if (pCounter->GetType() != GetType()) {
|
||||
G4ExceptionDescription errMsg;
|
||||
errMsg << "You are trying to absorb a counter with different type!" << G4endl;
|
||||
G4Exception(G4String("G4VUserMoleculeReactionCounter<"
|
||||
+ G4::MoleculeCounter::GetTemplateTypeName<TIndex>() + ">::AbsorbCounter"),
|
||||
"TYPE_DIFF", JustWarning, errMsg);
|
||||
}
|
||||
|
||||
for (auto const& worker_it : pCounter->GetCounterMap()) {
|
||||
auto [master_it, indexIsNew] =
|
||||
fCounterMap.emplace(worker_it.first, InnerCounterMapType{fTimeComparer});
|
||||
|
||||
G4int currentNumber = 0, previousNumber = 0;
|
||||
for (auto const& [time, number] : worker_it.second) {
|
||||
currentNumber = number - previousNumber;
|
||||
previousNumber = number;
|
||||
|
||||
if (master_it->second.empty()) {
|
||||
master_it->second.emplace(time, currentNumber);
|
||||
}
|
||||
else { // at least one element exists, so we can try to find the closest key
|
||||
auto it_closest = G4::MoleculeCounter::FindClosestEntryForKey(master_it->second, time);
|
||||
auto [it, _] = master_it->second.emplace(time, it_closest->second);
|
||||
do {
|
||||
it->second += currentNumber;
|
||||
} while (++it != master_it->second.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#endif
|
||||
@@ -18,6 +18,7 @@ geant4_add_module(G4emdna-utils
|
||||
G4DNAPTBExcitationStructure.hh
|
||||
G4DNAPTBIonisationStructure.hh
|
||||
G4DNARevertProbability.hh
|
||||
G4DNASamplingTable.hh
|
||||
G4DNAWaterExcitationStructure.hh
|
||||
G4DNAWaterIonisationStructure.hh
|
||||
G4ErrorFunction.hh
|
||||
@@ -36,6 +37,9 @@ geant4_add_module(G4emdna-utils
|
||||
G4DNAEventSet.hh
|
||||
G4ChemicalMoleculeFinder.hh
|
||||
G4DNAMaterialManager.hh
|
||||
G4MoleculeReactionCounter.hh
|
||||
G4VUserMoleculeReactionCounter.hh
|
||||
G4ChemEquilibrium.hh
|
||||
SOURCES
|
||||
G4DNAChemistryManager.cc
|
||||
G4DNACPA100LogLogInterpolation.cc
|
||||
@@ -51,6 +55,7 @@ geant4_add_module(G4emdna-utils
|
||||
G4DNAEmfietzoglouWaterIonisationStructure.cc
|
||||
G4DNAPTBExcitationStructure.cc
|
||||
G4DNAPTBIonisationStructure.cc
|
||||
G4DNASamplingTable.cc
|
||||
G4DNAWaterExcitationStructure.cc
|
||||
G4DNAWaterIonisationStructure.cc
|
||||
G4ErrorFunction.cc
|
||||
@@ -59,14 +64,15 @@ geant4_add_module(G4emdna-utils
|
||||
G4ReactionTableMessenger.cc
|
||||
G4VDNAReactionModel.cc
|
||||
G4VUserChemistryList.cc
|
||||
# physchemIO
|
||||
G4VPhysChemIO.cc
|
||||
G4PhysChemIO.cc
|
||||
G4IRTUtils.cc
|
||||
G4DNAScavengerMaterial.cc
|
||||
G4DNAMesh.cc
|
||||
G4DNAEventSet.cc
|
||||
G4DNAMaterialManager.cc)
|
||||
G4DNAMaterialManager.cc
|
||||
G4ChemEquilibrium.cc
|
||||
G4MoleculeReactionCounter.cc)
|
||||
|
||||
geant4_module_link_libraries(G4emdna-utils
|
||||
PUBLIC
|
||||
@@ -77,8 +83,8 @@ geant4_module_link_libraries(G4emdna-utils
|
||||
G4intercoms
|
||||
G4partman
|
||||
PRIVATE
|
||||
G4analysismng
|
||||
G4emdna-moltypes
|
||||
G4emutils
|
||||
G4geometrymng
|
||||
G4heprandom
|
||||
G4ions
|
||||
|
||||
+6
-1
@@ -36,6 +36,7 @@ G4ChemEquilibrium::G4ChemEquilibrium(const G4int& type, const G4double& time)
|
||||
|
||||
void G4ChemEquilibrium::Initialize()
|
||||
{
|
||||
Reset();
|
||||
MolType H2O =
|
||||
G4MoleculeTable::Instance()->GetConfiguration("H2O");
|
||||
MolType H3OpB =
|
||||
@@ -95,6 +96,9 @@ void G4ChemEquilibrium::PrintInfo() const
|
||||
|
||||
void G4ChemEquilibrium::SetEquilibrium(Reaction pReaction)
|
||||
{
|
||||
if(pReaction == nullptr){
|
||||
return;
|
||||
}
|
||||
if(pReaction->GetReactionType() != fRectionType)
|
||||
{
|
||||
std::vector<MolType> molVector;
|
||||
@@ -113,7 +117,8 @@ void G4ChemEquilibrium::SetEquilibrium(Reaction pReaction)
|
||||
{
|
||||
fAddEquilibrium = true;
|
||||
fEquilibriumTime = fGlobalTime;
|
||||
if(fVerbose >1) {
|
||||
if(fVerbose >1)
|
||||
{
|
||||
G4cout << "Reaction type : " << pReaction->GetReactionType() << " : "
|
||||
<< pReaction->GetReactant1()->GetName() << " + "
|
||||
<< pReaction->GetReactant2()->GetName() << G4endl;
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "G4H2O.hh"
|
||||
#include "G4MolecularConfiguration.hh"
|
||||
#include "G4Molecule.hh"
|
||||
#include "G4MoleculeCounterManager.hh"
|
||||
#include "G4MoleculeFinder.hh"
|
||||
#include "G4MoleculeTable.hh"
|
||||
#include "G4PhysChemIO.hh"
|
||||
@@ -186,7 +187,8 @@ void G4DNAChemistryManager::Clear()
|
||||
|
||||
G4DNAMolecularReactionTable::DeleteInstance();
|
||||
G4MolecularConfiguration::DeleteManager();
|
||||
G4VMoleculeCounter::DeleteInstance();
|
||||
if (G4MoleculeCounterManager::GetInstanceIfExists() != nullptr)
|
||||
G4MoleculeCounterManager::DeleteInstance();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -325,11 +327,9 @@ void G4DNAChemistryManager::Run()
|
||||
}
|
||||
|
||||
G4MoleculeTable::Instance()->Finalize();
|
||||
|
||||
G4Scheduler::Instance()->Process();
|
||||
if (fResetCounterWhenRunEnds)
|
||||
{
|
||||
G4VMoleculeCounter::Instance()->ResetCounter();
|
||||
}
|
||||
|
||||
CloseFile();
|
||||
}
|
||||
|
||||
@@ -418,6 +418,10 @@ void G4DNAChemistryManager::InitializeMaster()
|
||||
|
||||
G4Scheduler::Instance();
|
||||
// creates a concrete object of the scheduler
|
||||
|
||||
if (G4MoleculeCounterManager::GetInstanceIfExists() != nullptr)
|
||||
G4MoleculeCounterManager::Instance()->Initialize();
|
||||
|
||||
fMasterInitialized = true;
|
||||
}
|
||||
|
||||
@@ -484,9 +488,10 @@ void G4DNAChemistryManager::InitializeThread()
|
||||
|
||||
G4Scheduler::Instance()->Initialize();
|
||||
|
||||
fpThreadData->fThreadInitialized = true;
|
||||
if (G4MoleculeCounterManager::GetInstanceIfExists() != nullptr)
|
||||
G4MoleculeCounterManager::Instance()->Initialize();
|
||||
|
||||
G4VMoleculeCounter::InitializeInstance();
|
||||
fpThreadData->fThreadInitialized = true;
|
||||
|
||||
InitializeFile();
|
||||
}
|
||||
@@ -647,8 +652,9 @@ void G4DNAChemistryManager::CreateWaterMolecule(ElectronicModification modificat
|
||||
}
|
||||
}
|
||||
|
||||
G4Track* pH2OTrack = pH2OMolecule->BuildTrack(picosecond + delayedTime,
|
||||
pIncomingTrack->GetPosition());
|
||||
G4Track *pH2OTrack = pH2OMolecule->BuildTrack(picosecond + delayedTime,
|
||||
pIncomingTrack->GetPosition(),
|
||||
pIncomingTrack);
|
||||
|
||||
pH2OTrack->SetParentID(pIncomingTrack->GetTrackID());
|
||||
pH2OTrack->SetTrackStatus(fStopButAlive);
|
||||
@@ -683,8 +689,9 @@ void G4DNAChemistryManager::CreateSolvatedElectron(const G4Track* pIncomingTrack
|
||||
|
||||
PushMolecule(std::make_unique<G4Molecule>(G4Electron_aq::Definition()),
|
||||
picosecond + delayedTime,
|
||||
pFinalPosition != nullptr ? *pFinalPosition : pIncomingTrack->GetPosition(),
|
||||
pIncomingTrack->GetTrackID());
|
||||
pFinalPosition ? *pFinalPosition : pIncomingTrack->GetPosition(),
|
||||
pIncomingTrack->GetTrackID(),
|
||||
pIncomingTrack);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -692,13 +699,14 @@ void G4DNAChemistryManager::CreateSolvatedElectron(const G4Track* pIncomingTrack
|
||||
|
||||
void G4DNAChemistryManager::PushMolecule(std::unique_ptr<G4Molecule> pMolecule,
|
||||
double time,
|
||||
const G4ThreeVector& position,
|
||||
int parentID)
|
||||
const G4ThreeVector &position,
|
||||
int parentID,
|
||||
const G4Track *parentTrack)
|
||||
{
|
||||
assert(fActiveChemistry
|
||||
&& "To inject chemical species, the chemistry must be activated. "
|
||||
"Check chemistry activation before injecting species.");
|
||||
G4Track* pTrack = pMolecule->BuildTrack(time, position);
|
||||
G4Track* pTrack = pMolecule->BuildTrack(time, position, parentTrack);
|
||||
pTrack->SetTrackStatus(fAlive);
|
||||
pTrack->SetParentID(parentID);
|
||||
pMolecule.release();
|
||||
@@ -767,16 +775,30 @@ void G4DNAChemistryManager::SetVerbose(G4int verbose)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
G4bool G4DNAChemistryManager::IsCounterResetWhenRunEnds() const
|
||||
void G4DNAChemistryManager::BeginOfEventAction(const G4Event* pEvent)
|
||||
{
|
||||
return fResetCounterWhenRunEnds;
|
||||
G4MoleculeCounterManager::Instance()->BeginOfEventAction(pEvent);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4DNAChemistryManager::ResetCounterWhenRunEnds(G4bool resetCounterWhenRunEnds)
|
||||
void G4DNAChemistryManager::BeginOfRunAction(const G4Run* pRun)
|
||||
{
|
||||
fResetCounterWhenRunEnds = resetCounterWhenRunEnds;
|
||||
G4MoleculeCounterManager::Instance()->BeginOfRunAction(pRun);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4DNAChemistryManager::EndOfEventAction(const G4Event* pEvent)
|
||||
{
|
||||
G4MoleculeCounterManager::Instance()->EndOfEventAction(pEvent);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4DNAChemistryManager::EndOfRunAction(const G4Run* pRun) // for potential future use
|
||||
{
|
||||
G4MoleculeCounterManager::Instance()->EndOfRunAction(pRun);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -65,6 +65,10 @@ void Event::PrintEvent() const
|
||||
G4bool comparatorEventSet::operator()(std::unique_ptr<Event> const& rhs,
|
||||
std::unique_ptr<Event> const& lhs) const
|
||||
{
|
||||
if(rhs->GetTime() == lhs->GetTime())
|
||||
{
|
||||
return rhs->GetIndex() < lhs->GetIndex();
|
||||
}
|
||||
return rhs->GetTime() < lhs->GetTime();
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <algorithm>
|
||||
#include <ostream>
|
||||
#include "G4ITTrackHolder.hh"
|
||||
#include "Randomize.hh"
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, const G4VDNAMesh::Index& rhs)
|
||||
{
|
||||
@@ -232,3 +233,32 @@ G4VDNAMesh::Index G4DNAMesh::ConvertIndex(const Index& index,
|
||||
}
|
||||
return Index{ dx, dy, dz };
|
||||
}
|
||||
|
||||
G4VDNAMesh::Index G4DNAMesh:: GetRandomIndex(const Index& oldIndex, const G4double& OldReso) const
|
||||
{
|
||||
G4double x_min = oldIndex.x * OldReso;
|
||||
G4double x_max = (oldIndex.x + 1) * OldReso;
|
||||
G4double y_min = oldIndex.y * OldReso;
|
||||
G4double y_max = (oldIndex.y + 1) * OldReso;
|
||||
G4double z_min = oldIndex.z * OldReso;
|
||||
G4double z_max = (oldIndex.z + 1) * OldReso;
|
||||
|
||||
G4int i_max = std::floor(x_max / fResolution);
|
||||
G4int j_max = std::floor(y_max / fResolution);
|
||||
G4int k_max = std::floor(z_max / fResolution);
|
||||
|
||||
G4int i_min = std::floor(x_min / fResolution);
|
||||
G4int j_min = std::floor(y_min / fResolution);
|
||||
G4int k_min = std::floor(z_min / fResolution);
|
||||
|
||||
G4double r1 = G4UniformRand();
|
||||
G4double r2 = G4UniformRand();
|
||||
G4double r3 = G4UniformRand();
|
||||
|
||||
G4int i_n = i_min + (G4int)std::floor(r1 * (i_max - i_min + 1));
|
||||
G4int j_n = j_min + (G4int)std::floor(r2 * (j_max - j_min + 1));
|
||||
G4int k_n = k_min + (G4int)std::floor(r3 * (k_max - k_min + 1));
|
||||
|
||||
return Index{ i_n, j_n, k_n };
|
||||
}
|
||||
|
||||
|
||||
@@ -292,15 +292,20 @@ void G4DNAMolecularReactionData::SetReactionType(G4int type)
|
||||
fDiffusionRate = 4 * pi * sumDiffCoeff * fReactionRadius * Avogadro;
|
||||
if (fpReactant1 == fpReactant2) fDiffusionRate/=2;
|
||||
fActivationRate = fDiffusionRate * fObservedReactionRate / (fDiffusionRate - fObservedReactionRate);
|
||||
fProbability = Rs / (Rs + (fDiffusionRate / fActivationRate) * (fReactionRadius + Rs));
|
||||
|
||||
if(fActivationRate > 0) {
|
||||
fProbability =
|
||||
Rs / (Rs + (fDiffusionRate / fActivationRate) * (fReactionRadius + Rs));
|
||||
}
|
||||
}else{ // Type IV
|
||||
fEffectiveReactionRadius = -fOnsagerRadius/(1-exp(fOnsagerRadius/fReactionRadius));
|
||||
fDiffusionRate = 4 * pi * sumDiffCoeff * fEffectiveReactionRadius * Avogadro;
|
||||
if (fpReactant1 == fpReactant2) fDiffusionRate/=2;
|
||||
|
||||
fActivationRate = fDiffusionRate * fObservedReactionRate / (fDiffusionRate - fObservedReactionRate);
|
||||
fProbability = Rs / (Rs + (fDiffusionRate / fActivationRate) * (fEffectiveReactionRadius + Rs));
|
||||
if(fActivationRate > 0) {
|
||||
fProbability =
|
||||
Rs / (Rs + (fDiffusionRate / fActivationRate) * (fEffectiveReactionRadius + Rs));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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 "G4DNASamplingTable.hh"
|
||||
#include "G4EmParameters.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4Log.hh"
|
||||
#include "G4Exp.hh"
|
||||
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
G4DNASamplingTable::G4DNASamplingTable(std::size_t npoints)
|
||||
{
|
||||
fPrimaryEnergy.reserve(npoints);
|
||||
fSecEnergy.reserve(npoints);
|
||||
for (G4int i=0; i<5; ++i) { (fPDF[i]).reserve(npoints); }
|
||||
}
|
||||
|
||||
G4DNASamplingTable::~G4DNASamplingTable()
|
||||
{
|
||||
for (auto & p : fSecEnergy) { delete p; }
|
||||
for (G4int i=0; i<5; ++i) {
|
||||
for (auto & p : fPDF[i]) { delete p; }
|
||||
}
|
||||
}
|
||||
|
||||
void G4DNASamplingTable::LoadData(const G4String& fname, G4double factE,
|
||||
G4double fact, G4bool verbose)
|
||||
{
|
||||
std::ostringstream ost;
|
||||
ost << G4EmParameters::Instance()->GetDirLEDATA() << "/" << fname;
|
||||
std::ifstream fin(ost.str().c_str());
|
||||
if (!fin.is_open()) {
|
||||
G4ExceptionDescription ed;
|
||||
ed << "File <" << ost.str().c_str() << "> is not opened!";
|
||||
G4Exception("G4DNASamplingTable::LoadDifferential ", "em0003",
|
||||
FatalException, ed, "");
|
||||
return;
|
||||
}
|
||||
|
||||
G4double t, e, sig;
|
||||
G4double e0{0.0};
|
||||
G4int ntmax{0};
|
||||
G4int nt{0};
|
||||
std::vector<G4double>* v = nullptr;
|
||||
std::vector<G4double>* vPDF[5];
|
||||
for (;;) {
|
||||
fin >> e;
|
||||
if (fin.eof()) { break; }
|
||||
if (e != e0 || nullptr == v) {
|
||||
fPrimaryEnergy.push_back(e*factE);
|
||||
e0 = e;
|
||||
++fNpoints;
|
||||
v = new std::vector<G4double>;
|
||||
fSecEnergy.push_back(v);
|
||||
for (G4int i=0; i<5; ++i) {
|
||||
vPDF[i] = new std::vector<G4double>;
|
||||
(fPDF[i]).push_back(vPDF[i]);
|
||||
}
|
||||
ntmax = std::max(ntmax, nt);
|
||||
nt = 0;
|
||||
}
|
||||
fin >> t;
|
||||
v->push_back(t*factE);
|
||||
++nt;
|
||||
for (G4int i=0; i<5; ++i) {
|
||||
fin >> sig;
|
||||
sig *= fact;
|
||||
(vPDF[i])->push_back(sig);
|
||||
}
|
||||
if (fin.eof()) { break; }
|
||||
}
|
||||
if (verbose) {
|
||||
G4cout << "G4DNASamplingTable::LoadData from file:" << G4endl;
|
||||
G4cout << fname << G4endl;
|
||||
G4cout << " Nenergy= " << fNpoints << " NmaxT= " << ntmax << G4endl;
|
||||
}
|
||||
if (fNpoints > 0) { --fNpoints; }
|
||||
}
|
||||
|
||||
G4double G4DNASamplingTable::GetValue(G4double ekinPrimary,
|
||||
G4double ekinSec, G4int shell) const
|
||||
{
|
||||
std::vector<G4double>* e1{nullptr};
|
||||
std::vector<G4double>* e2{nullptr};
|
||||
std::vector<G4double>* s1{nullptr};
|
||||
std::vector<G4double>* s2{nullptr};
|
||||
G4int idx = GetIndex(fPrimaryEnergy, ekinPrimary);
|
||||
if (idx == -1) {
|
||||
e1 = fSecEnergy[0];
|
||||
s1 = (fPDF[shell])[0];
|
||||
} else if (idx > fNpoints) {
|
||||
e1 = fSecEnergy[fNpoints];
|
||||
s1 = (fPDF[shell])[fNpoints];
|
||||
} else {
|
||||
e1 = fSecEnergy[idx];
|
||||
s1 = (fPDF[shell])[idx];
|
||||
e2 = fSecEnergy[idx + 1];
|
||||
s2 = (fPDF[shell])[idx + 1];
|
||||
}
|
||||
// edge cases
|
||||
G4double res1 = VecInterpolation(e1, s1, ekinSec);
|
||||
if (nullptr == e2) { return res1; }
|
||||
|
||||
// ordinary case
|
||||
G4double res2 = VecInterpolation(e2, s2, ekinSec);
|
||||
G4double res = Interpolate(fPrimaryEnergy[idx], fPrimaryEnergy[idx + 1],
|
||||
ekinPrimary, res1, res2);
|
||||
return res;
|
||||
}
|
||||
|
||||
G4int G4DNASamplingTable::GetIndex(const std::vector<G4double>& v, G4double x) const
|
||||
{
|
||||
G4int idx;
|
||||
if (x <= v[0]) { idx = -1; }
|
||||
else if (x >= v.back()) { idx = (G4int)v.size(); }
|
||||
else {
|
||||
std::size_t i = std::upper_bound(v.cbegin(), v.cend(), x) - v.cbegin() - 1;
|
||||
idx = (G4int)i;
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
G4double G4DNASamplingTable::VecInterpolation(const std::vector<G4double>* ener,
|
||||
const std::vector<G4double>* val,
|
||||
G4double e) const
|
||||
{
|
||||
G4int idx = GetIndex(*ener, e);
|
||||
G4double res;
|
||||
if (idx == -1) { res = (*val)[0]; }
|
||||
else if (e >= ener->back()) { res = val->back(); }
|
||||
else {
|
||||
res = Interpolate((*ener)[idx], (*ener)[idx + 1], e, (*val)[idx], (*val)[idx + 1]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
G4double G4DNASamplingTable::Interpolate(G4double e1, G4double e2, G4double e,
|
||||
G4double xs1, G4double xs2) const
|
||||
{
|
||||
G4double res;
|
||||
// special case
|
||||
if (e1 == e2) {
|
||||
res = 0.5 * (xs1 + xs2);
|
||||
|
||||
// Log-log interpolation by default
|
||||
} else if (e1 > 0.0 && e2 > 0.0 && xs1 > 0.0 && xs2 > 0.0) {
|
||||
G4double y = G4Log(xs1) + G4Log(e/e1) * G4Log(xs2/xs1)/G4Log(e2/e1);
|
||||
res = G4Exp(y);
|
||||
|
||||
// Lin-Log interpolation
|
||||
} else if (xs1 > 0.0 && xs2 > 0.0) {
|
||||
G4double y = G4Log(xs1) + (e - e1) * G4Log(xs2/xs1)/(e2 - e1);
|
||||
res = G4Exp(y);
|
||||
|
||||
// Lin-Lin interpolation
|
||||
} else {
|
||||
res = xs1 + (e - e1) * (xs2 - xs1)/(e2 - e1);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
G4double
|
||||
G4DNASamplingTable::SampleCumulative(G4double ekinPrimary, G4int shell) const
|
||||
{
|
||||
std::vector<G4double>* e1{nullptr};
|
||||
std::vector<G4double>* e2{nullptr};
|
||||
std::vector<G4double>* s1{nullptr};
|
||||
std::vector<G4double>* s2{nullptr};
|
||||
G4int idx = GetIndex(fPrimaryEnergy, ekinPrimary);
|
||||
if (idx == -1) {
|
||||
e1 = fSecEnergy[0];
|
||||
s1 = (fPDF[shell])[0];
|
||||
} else if (idx > fNpoints) {
|
||||
e1 = fSecEnergy[fNpoints];
|
||||
s1 = (fPDF[shell])[fNpoints];
|
||||
} else {
|
||||
e1 = fSecEnergy[idx];
|
||||
s1 = (fPDF[shell])[idx];
|
||||
e2 = fSecEnergy[idx + 1];
|
||||
s2 = (fPDF[shell])[idx + 1];
|
||||
}
|
||||
G4double q = G4UniformRand();
|
||||
|
||||
// edge cases
|
||||
G4double res1 = VecInterpolation(s1, e1, q);
|
||||
if (nullptr == e2) { return res1; }
|
||||
|
||||
// ordinary case
|
||||
G4double res2 = VecInterpolation(s2, e2, q);
|
||||
G4double res = Interpolate(fPrimaryEnergy[idx], fPrimaryEnergy[idx + 1],
|
||||
ekinPrimary, res1, res2);
|
||||
return res;
|
||||
}
|
||||
@@ -60,6 +60,19 @@ void G4DNAScavengerMaterial::Initialize()
|
||||
G4cout << "G4DNAScavengerMaterial existed but empty" << G4endl;
|
||||
}
|
||||
Reset();
|
||||
|
||||
fEquilibriumProcesses.emplace(
|
||||
std::make_pair(6, std::make_unique<G4ChemEquilibrium>(6, 10 * CLHEP::us)));//reactionType6 and 10 * us
|
||||
fEquilibriumProcesses.emplace(
|
||||
std::make_pair(7, std::make_unique<G4ChemEquilibrium>(7, 10 * CLHEP::us)));//reactionType6 and 10 * us
|
||||
fEquilibriumProcesses.emplace(
|
||||
std::make_pair(8, std::make_unique<G4ChemEquilibrium>(8, 10 * CLHEP::us)));//reactionType6 and 10 * us
|
||||
for(auto& it : fEquilibriumProcesses)
|
||||
{
|
||||
it.second->Initialize();
|
||||
it.second->SetVerbose(fVerbose);
|
||||
}
|
||||
|
||||
fIsInitialized = true;
|
||||
}
|
||||
|
||||
@@ -68,10 +81,7 @@ G4DNAScavengerMaterial::GetNumberMoleculePerVolumeUnitForMaterialConf(MolType ma
|
||||
{
|
||||
// no change these molecules
|
||||
if (fH2O == matConf) {
|
||||
G4ExceptionDescription exceptionDescription;
|
||||
exceptionDescription << "matConf : " << matConf->GetName();
|
||||
G4Exception("G4DNAScavengerMaterial::GetNumberMoleculePerVolumeUnitForMaterialConf",
|
||||
"G4DNAScavengerMaterial001", FatalErrorInArgument, exceptionDescription);
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto iter = fScavengerTable.find(matConf);
|
||||
@@ -118,7 +128,7 @@ void G4DNAScavengerMaterial::AddNumberMoleculePerVolumeUnitForMaterialConf(MolTy
|
||||
// no change these molecules
|
||||
|
||||
if (fH2O == matConf || fH3Op == matConf || // pH has no change
|
||||
G4MoleculeTable::Instance()->GetConfiguration("OHm(B)") == matConf)
|
||||
fHOm == matConf)
|
||||
{
|
||||
// G4cout<<"moletype : "<<matConf->GetName()<<G4endl;
|
||||
// kobs is already counted these molecule concentrations
|
||||
@@ -173,6 +183,8 @@ void G4DNAScavengerMaterial::Reset()
|
||||
return;
|
||||
}
|
||||
|
||||
ResetEquilibrium();
|
||||
|
||||
fScavengerTable.clear();
|
||||
fCounterMap.clear();
|
||||
fpLastSearch.reset(nullptr);
|
||||
@@ -213,12 +225,17 @@ void G4DNAScavengerMaterial::AddAMoleculeAtTime(MolType molecule, G4double time,
|
||||
auto end = counterMap_i->second.rbegin();
|
||||
|
||||
if (end->first <= time
|
||||
|| fabs(end->first - time) <= G4::MoleculeCounter::TimePrecision::fPrecision) {
|
||||
|| fabs(end->first - time) <= G4::MoleculeCounter::FixedTimeComparer::fPrecision) {
|
||||
G4double newValue = end->second + number;
|
||||
counterMap_i->second[time] = newValue;
|
||||
if (newValue != (floor)(fScavengerTable[molecule])) // protection
|
||||
{
|
||||
G4String errMsg = "You are trying to add wrong molecule ";
|
||||
G4String errMsg = "You are trying to add wrong molecule : ";
|
||||
G4cout<< " newValue : "<<newValue<<" " << molecule->GetName()
|
||||
<< " at time : " << G4BestUnit(time, "Time")
|
||||
<< " with number : " << number
|
||||
<<" (floor)(fScavengerTable[molecule]) : "<<(floor)(fScavengerTable[molecule])
|
||||
<< " and the final number is not valid." << G4endl;
|
||||
G4Exception("AddAMoleculeAtTime", "", FatalErrorInArgument, errMsg);
|
||||
}
|
||||
}
|
||||
@@ -427,4 +444,37 @@ G4double G4DNAScavengerMaterial::GetpH()
|
||||
fScavengerTable[fHOm] = 0;
|
||||
}
|
||||
return -pH;
|
||||
}
|
||||
|
||||
G4bool G4DNAScavengerMaterial::SetEquilibrium(const G4DNAMolecularReactionData* pReaction,
|
||||
G4double time)
|
||||
{
|
||||
for(auto& it : fEquilibriumProcesses)
|
||||
{
|
||||
it.second->SetGlobalTime(time);
|
||||
it.second->SetEquilibrium(pReaction);
|
||||
if(it.second->IsStatusChanged()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void G4DNAScavengerMaterial::ResetEquilibrium()
|
||||
{
|
||||
for(auto& it : fEquilibriumProcesses)
|
||||
{
|
||||
it.second->Reset();
|
||||
}
|
||||
}
|
||||
|
||||
G4bool G4DNAScavengerMaterial::IsEquilibrium(const G4int& reactionType) const
|
||||
{
|
||||
auto reaction = fEquilibriumProcesses.find(reactionType);
|
||||
if(reaction == fEquilibriumProcesses.end())
|
||||
{
|
||||
return true;
|
||||
}else
|
||||
{
|
||||
return (reaction->second->GetEquilibriumStatus());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// Author: Christian Velten (2025)
|
||||
|
||||
#include "G4MoleculeReactionCounter.hh"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
G4String G4MoleculeReactionCounterIndex::FormattedReactionString(const G4DNAMolecularReactionData* reactionData) const
|
||||
{
|
||||
const G4MolecularConfiguration* reactant1 = reactionData->GetReactant1();
|
||||
const G4MolecularConfiguration* reactant2 = reactionData->GetReactant2();
|
||||
|
||||
const std::vector<const G4MolecularConfiguration*>* products = reactionData->GetProducts();
|
||||
|
||||
G4String reactionLhs = "";
|
||||
if (reactant1 != nullptr) {
|
||||
reactionLhs += reactant1->GetUserID();
|
||||
if (reactant2 != nullptr) reactionLhs += " + ";
|
||||
}
|
||||
if (reactant2 != nullptr) reactionLhs += reactant2->GetUserID();
|
||||
|
||||
G4String reactionRhs = "";
|
||||
for (auto it = products->cbegin(); it != products->cend(); ++it) {
|
||||
if (*it != nullptr) {
|
||||
if (it != products->cbegin() && reactionRhs.size() > 0) reactionRhs += " + ";
|
||||
reactionRhs += (*it)->GetUserID();
|
||||
}
|
||||
}
|
||||
|
||||
G4String reactionString = reactionLhs + " -> " + reactionRhs;
|
||||
|
||||
return reactionString;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
G4MoleculeReactionCounter::G4MoleculeReactionCounter() : G4VUserMoleculeReactionCounter() {}
|
||||
|
||||
G4MoleculeReactionCounter::G4MoleculeReactionCounter(G4String name)
|
||||
: G4VUserMoleculeReactionCounter(std::move(name), MoleculeReactionCounterType::Basic)
|
||||
{}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4MoleculeReactionCounter::InitializeUser() {}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
std::unique_ptr<G4VMoleculeReactionCounter::G4VMoleculeReactionCounterIndex>
|
||||
G4MoleculeReactionCounter::BuildSimpleIndex(const G4DNAMolecularReactionData* reactionData) const
|
||||
{
|
||||
return std::make_unique<G4MoleculeReactionCounterIndex>(reactionData);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -33,7 +33,6 @@
|
||||
#include "G4PhysChemIO.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4Track.hh"
|
||||
#include "G4VAnalysisManager.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -42,7 +41,6 @@ using namespace std;
|
||||
namespace G4PhysChemIO{
|
||||
|
||||
FormattedText::FormattedText(){
|
||||
fRunID = -1;
|
||||
fEventID = -1;
|
||||
fFileInitialized = false;
|
||||
}
|
||||
@@ -154,155 +152,4 @@ void FormattedText::CreateSolvatedElectron(const G4Track* theIncomingTrack,
|
||||
fOfstream << G4endl;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Using G4analysis
|
||||
//
|
||||
|
||||
G4Analysis::G4Analysis(G4VAnalysisManager* analysisManager):
|
||||
fpAnalysisManager(analysisManager)
|
||||
{
|
||||
fFileInitialized = false;
|
||||
fNtupleID = -1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
G4Analysis::~G4Analysis()
|
||||
{
|
||||
fpAnalysisManager = nullptr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4Analysis::InitializeFile()
|
||||
{
|
||||
if (fFileInitialized) return;
|
||||
|
||||
fNtupleID = fpAnalysisManager->CreateNtuple("PhysChem","PhysChem");
|
||||
fpAnalysisManager->CreateNtupleIColumn(fNtupleID, "ParentID");
|
||||
fpAnalysisManager->CreateNtupleSColumn(fNtupleID, "Molecule");
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// valid for H2O only
|
||||
fpAnalysisManager->CreateNtupleIColumn(fNtupleID, "ElectronicModif");
|
||||
// ionization = 0 / excitation = 1 / diss att = 2
|
||||
fpAnalysisManager->CreateNtupleIColumn(fNtupleID, "level");
|
||||
// valid for ion and exc only
|
||||
fpAnalysisManager->CreateNtupleDColumn(fNtupleID, "Energy_eV");
|
||||
// valid for ion and exc only
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
fpAnalysisManager->CreateNtupleDColumn(fNtupleID, "x_parent_nm");
|
||||
fpAnalysisManager->CreateNtupleDColumn(fNtupleID, "y_parent_nm");
|
||||
fpAnalysisManager->CreateNtupleDColumn(fNtupleID, "z_parent_nm");
|
||||
fpAnalysisManager->CreateNtupleDColumn(fNtupleID, "x_nm");
|
||||
fpAnalysisManager->CreateNtupleDColumn(fNtupleID, "y_nm");
|
||||
fpAnalysisManager->CreateNtupleDColumn(fNtupleID, "z_nm");
|
||||
fpAnalysisManager->FinishNtuple(fNtupleID);
|
||||
|
||||
fFileInitialized = true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4Analysis::WriteInto(const G4String& output,
|
||||
ios_base::openmode)
|
||||
{
|
||||
fpAnalysisManager->OpenFile(output);
|
||||
fFileInitialized = false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4Analysis::CloseFile()
|
||||
{
|
||||
// fpAnalysisManager->Write();
|
||||
// fpAnalysisManager->CloseFile();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4Analysis::CreateWaterMolecule(G4int modification,
|
||||
G4int electronicLevel,
|
||||
G4double energy,
|
||||
const G4Track* theIncomingTrack)
|
||||
{
|
||||
if(!fFileInitialized) InitializeFile();
|
||||
|
||||
// parent ID
|
||||
fpAnalysisManager->FillNtupleIColumn(fNtupleID, 0,
|
||||
theIncomingTrack->GetTrackID());
|
||||
|
||||
// molecule type
|
||||
fpAnalysisManager->FillNtupleSColumn(fNtupleID, 1, "H2O");
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// valid for H2O only
|
||||
|
||||
// electronic modif
|
||||
fpAnalysisManager->FillNtupleIColumn(fNtupleID, 2, modification);
|
||||
// ionization = 0 / excitation = 1 / diss att = 2
|
||||
fpAnalysisManager->FillNtupleIColumn(fNtupleID, 3, electronicLevel);
|
||||
fpAnalysisManager->FillNtupleDColumn(fNtupleID, 4, energy / eV);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const G4ThreeVector& parentPos = theIncomingTrack->GetPosition();
|
||||
|
||||
fpAnalysisManager->FillNtupleDColumn(fNtupleID,5,(parentPos.x())/nanometer);
|
||||
fpAnalysisManager->FillNtupleDColumn(fNtupleID,6,(parentPos.y())/nanometer);
|
||||
fpAnalysisManager->FillNtupleDColumn(fNtupleID,7,(parentPos.z())/nanometer);
|
||||
|
||||
fpAnalysisManager->FillNtupleDColumn(fNtupleID,8,(parentPos.x())/nanometer);
|
||||
fpAnalysisManager->FillNtupleDColumn(fNtupleID,9,(parentPos.y())/nanometer);
|
||||
fpAnalysisManager->FillNtupleDColumn(fNtupleID,10,(parentPos.z())/nanometer);
|
||||
fpAnalysisManager->AddNtupleRow(fNtupleID);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void G4Analysis::CreateSolvatedElectron(const G4Track* electronTrack,
|
||||
G4ThreeVector* finalPosition)
|
||||
{
|
||||
if(!fFileInitialized) InitializeFile();
|
||||
|
||||
// parent ID
|
||||
fpAnalysisManager->FillNtupleIColumn(fNtupleID, 0,
|
||||
electronTrack->GetTrackID());
|
||||
|
||||
// molecule type
|
||||
fpAnalysisManager->FillNtupleSColumn(fNtupleID, 1, "e_aq");
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// valid for H2O only
|
||||
|
||||
// electronic modif
|
||||
fpAnalysisManager->FillNtupleIColumn(fNtupleID, 2, -1); // electronic modif
|
||||
fpAnalysisManager->FillNtupleIColumn(fNtupleID, 3, -1); // electronic level
|
||||
fpAnalysisManager->FillNtupleDColumn(fNtupleID, 4,
|
||||
electronTrack->GetKineticEnergy() / eV);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const G4ThreeVector& parentPos = electronTrack->GetPosition();
|
||||
const double i_nm = 1./nanometer;
|
||||
|
||||
fpAnalysisManager->FillNtupleDColumn(fNtupleID,5, parentPos.x() *i_nm);
|
||||
fpAnalysisManager->FillNtupleDColumn(fNtupleID,6, parentPos.y() *i_nm);
|
||||
fpAnalysisManager->FillNtupleDColumn(fNtupleID,7, parentPos.z() *i_nm);
|
||||
|
||||
if (finalPosition != nullptr)
|
||||
{
|
||||
fpAnalysisManager->FillNtupleDColumn(fNtupleID,8, finalPosition->x()*i_nm);
|
||||
fpAnalysisManager->FillNtupleDColumn(fNtupleID,9, finalPosition->y()*i_nm);
|
||||
fpAnalysisManager->FillNtupleDColumn(fNtupleID,10, finalPosition->z()*i_nm);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpAnalysisManager->FillNtupleDColumn(fNtupleID,8, parentPos.x() *i_nm);
|
||||
fpAnalysisManager->FillNtupleDColumn(fNtupleID,9, parentPos.y() *i_nm);
|
||||
fpAnalysisManager->FillNtupleDColumn(fNtupleID,10, parentPos.z() *i_nm);
|
||||
}
|
||||
|
||||
fpAnalysisManager->AddNtupleRow(fNtupleID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,11 +6,20 @@ It must **not** be used as a substitute for writing good git commit messages!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 2025-02-07 L. Pandola (emlowen-V11-02-08)
|
||||
- Fix residual Coverity defect on G4ShellData
|
||||
## 2025-05-25 V. Ivanchenko (emlowen-V11-03-03)
|
||||
- G4LivermorePhotoElectricModel - reorganisation of initialisation and data
|
||||
destruction.
|
||||
- G4AtomicTransitionManager, G4UAtomicDeexcitation - use std::size_t and few
|
||||
other cosmetic changes.
|
||||
|
||||
## 2025-01-09 L. Pandola
|
||||
- Fix Coverity warnings in Penenelope models, G4ShellData, G4FluoData and
|
||||
## 2025-04-01 V. Ivanchenko (emlowen-V11-03-02)
|
||||
- G4hIonEffChargeSquare - fixed Coverity warning.
|
||||
|
||||
## 2025-02-07 L. Pandola (emlowen-V11-03-01)
|
||||
- Fix residual Coverity defect on G4ShellData.
|
||||
|
||||
## 2025-01-09 L. Pandola (emlowen-V11-03-00)
|
||||
- Fix Coverity warnings in Penenelope models, G4ShellData, G4FluoData and
|
||||
G4AugerTransition
|
||||
|
||||
## 2024-12-02 A. Ribon (emlowen-V11-02-07)
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
class G4AtomicDeexcitation {
|
||||
public:
|
||||
///constructor
|
||||
explicit G4AtomicDeexcitation();
|
||||
G4AtomicDeexcitation();
|
||||
~G4AtomicDeexcitation();
|
||||
|
||||
/// Returns a vector contains the photons generated by radiative transitions
|
||||
|
||||
@@ -61,19 +61,21 @@ public:
|
||||
/// function Instance()
|
||||
static G4AtomicTransitionManager* Instance();
|
||||
|
||||
~G4AtomicTransitionManager();
|
||||
|
||||
/// needs to be called once from other code before start of run
|
||||
void Initialise();
|
||||
|
||||
/// Z is the atomic number of the element, shellIndex is the
|
||||
/// index (in EADL) of the shell
|
||||
G4AtomicShell* Shell(G4int Z, size_t shellIndex) const;
|
||||
G4AtomicShell* Shell(G4int Z, std::size_t shellIndex) const;
|
||||
|
||||
/// Z is the atomic number of the element, shellIndex is the
|
||||
/// index (in EADL) of the final shell for the transition
|
||||
/// This function gives, upon Z and the Index of the initial shell where
|
||||
/// the vacancy is, the radiative transition that can happen (originating
|
||||
/// shell, energy, probability)
|
||||
const G4FluoTransition* ReachableShell(G4int Z, size_t shellIndex) const;
|
||||
const G4FluoTransition* ReachableShell(G4int Z, std::size_t shellIndex) const;
|
||||
|
||||
/// This function gives, upon Z and the Index of the initial shell where
|
||||
/// the vacancy is, the NON-radiative transition that can happen with
|
||||
@@ -98,26 +100,25 @@ public:
|
||||
/// Gives the sum of the probabilities of radiative transition towards the
|
||||
/// shell whose index is shellIndex
|
||||
G4double
|
||||
TotalRadiativeTransitionProbability(G4int Z, size_t shellIndex) const;
|
||||
TotalRadiativeTransitionProbability(G4int Z, std::size_t shellIndex) const;
|
||||
|
||||
/// Gives the sum of the probabilities of non radiative transition from the
|
||||
/// shell whose index is shellIndex
|
||||
G4double
|
||||
TotalNonRadiativeTransitionProbability(G4int Z, size_t shellIndex) const;
|
||||
TotalNonRadiativeTransitionProbability(G4int Z, std::size_t shellIndex) const;
|
||||
|
||||
/// Verbosity control
|
||||
void SetVerboseLevel(G4int vl) {verboseLevel = vl;};
|
||||
G4int GetVerboseLevel(){return verboseLevel;};
|
||||
|
||||
private:
|
||||
explicit G4AtomicTransitionManager();
|
||||
|
||||
~G4AtomicTransitionManager();
|
||||
|
||||
// Hide copy constructor and assignment operator
|
||||
G4AtomicTransitionManager& operator=(const G4AtomicTransitionManager& right);
|
||||
G4AtomicTransitionManager(const G4AtomicTransitionManager&);
|
||||
|
||||
G4AtomicTransitionManager& operator=
|
||||
(const G4AtomicTransitionManager& right) = delete;
|
||||
G4AtomicTransitionManager(const G4AtomicTransitionManager&) = delete;
|
||||
|
||||
private:
|
||||
G4AtomicTransitionManager();
|
||||
|
||||
static G4AtomicTransitionManager* instance;
|
||||
// since Augereffect data r stored as a table in G4AugerData, we have
|
||||
// here a pointer to an element of that class itself.
|
||||
|
||||
@@ -67,8 +67,6 @@ public:
|
||||
const G4MaterialCutsCouple*, const G4DynamicParticle*,
|
||||
G4double tmin, G4double maxEnergy) override;
|
||||
|
||||
void InitialiseForElement(const G4ParticleDefinition*, G4int Z) override;
|
||||
|
||||
[[maybe_unused]] inline void SetLimitNumberOfShells(G4int n) { nShellLimit = n; };
|
||||
G4double GetBindingEnergy(G4int Z, G4int shell);
|
||||
|
||||
@@ -82,7 +80,7 @@ protected:
|
||||
private:
|
||||
void ReadData(const G4int Z);
|
||||
|
||||
const G4String& FindDirectoryPath();
|
||||
void FindDirectoryPath();
|
||||
|
||||
void InitialiseOnFly(G4int Z);
|
||||
|
||||
|
||||
@@ -60,8 +60,8 @@ class G4Material;
|
||||
class G4UAtomicDeexcitation : public G4VAtomDeexcitation
|
||||
{
|
||||
public:
|
||||
explicit G4UAtomicDeexcitation();
|
||||
virtual ~G4UAtomicDeexcitation();
|
||||
G4UAtomicDeexcitation();
|
||||
~G4UAtomicDeexcitation() override;
|
||||
|
||||
//=================================================================
|
||||
// methods that are requested to be implemented by the interface
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "G4FluoData.hh"
|
||||
#include "G4AugerData.hh"
|
||||
#include "G4AutoLock.hh"
|
||||
|
||||
namespace { G4Mutex AtomicTransitionManagerMutex = G4MUTEX_INITIALIZER; }
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
@@ -48,7 +49,8 @@ G4AtomicTransitionManager* G4AtomicTransitionManager::instance = nullptr;
|
||||
G4AtomicTransitionManager* G4AtomicTransitionManager::Instance()
|
||||
{
|
||||
if (instance == nullptr) {
|
||||
instance = new G4AtomicTransitionManager();
|
||||
static G4AtomicTransitionManager man;
|
||||
instance = &man;
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
@@ -65,29 +67,20 @@ G4AtomicTransitionManager::~G4AtomicTransitionManager()
|
||||
{
|
||||
delete augerData;
|
||||
|
||||
for (auto& pos : shellTable){
|
||||
std::vector<G4AtomicShell*>vec = pos.second;
|
||||
std::size_t vecSize = vec.size();
|
||||
for (std::size_t i=0; i< vecSize; ++i){
|
||||
G4AtomicShell* shell = vec[i];
|
||||
delete shell;
|
||||
}
|
||||
for (auto const & pos : shellTable) {
|
||||
std::vector<G4AtomicShell*> vec = pos.second;
|
||||
for (auto const & p : vec) { delete p; }
|
||||
}
|
||||
|
||||
for (auto& ppos : transitionTable)
|
||||
{
|
||||
std::vector<G4FluoTransition*>vec = ppos.second;
|
||||
std::size_t vecSize=vec.size();
|
||||
|
||||
for (std::size_t i=0; i< vecSize; ++i){
|
||||
G4FluoTransition* transition = vec[i];
|
||||
delete transition;
|
||||
}
|
||||
}
|
||||
for (auto const & ppos : transitionTable) {
|
||||
std::vector<G4FluoTransition*> vec = ppos.second;
|
||||
for (auto const & p : vec) { delete p; }
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
G4AtomicShell*
|
||||
G4AtomicTransitionManager::Shell(G4int Z, size_t shellIndex) const
|
||||
G4AtomicTransitionManager::Shell(G4int Z, std::size_t shellIndex) const
|
||||
{
|
||||
auto pos = shellTable.find(Z);
|
||||
|
||||
@@ -98,7 +91,7 @@ G4AtomicTransitionManager::Shell(G4int Z, size_t shellIndex) const
|
||||
|
||||
else
|
||||
{
|
||||
size_t lastShell = v.size();
|
||||
std::size_t lastShell = v.size();
|
||||
G4ExceptionDescription ed;
|
||||
ed << "No de-excitation for Z= " << Z
|
||||
<< " shellIndex= " << shellIndex
|
||||
@@ -118,7 +111,7 @@ G4AtomicTransitionManager::Shell(G4int Z, size_t shellIndex) const
|
||||
G4Exception("G4AtomicTransitionManager::Shell()","de0001",
|
||||
FatalException,ed,"");
|
||||
}
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
@@ -127,7 +120,7 @@ G4AtomicTransitionManager::Shell(G4int Z, size_t shellIndex) const
|
||||
// the vacancy is, the radiative transition that can happen (originating
|
||||
// shell, energy, probability)
|
||||
const G4FluoTransition*
|
||||
G4AtomicTransitionManager::ReachableShell(G4int Z,size_t shellIndex) const
|
||||
G4AtomicTransitionManager::ReachableShell(G4int Z, std::size_t shellIndex) const
|
||||
{
|
||||
auto pos = transitionTable.find(Z);
|
||||
if (pos!= transitionTable.end())
|
||||
@@ -215,7 +208,7 @@ G4int G4AtomicTransitionManager::NumberOfReachableAugerShells(G4int Z)const
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
G4double G4AtomicTransitionManager::TotalRadiativeTransitionProbability(
|
||||
G4int Z, size_t shellIndex) const
|
||||
G4int Z, std::size_t shellIndex) const
|
||||
{
|
||||
auto pos = transitionTable.find(Z);
|
||||
G4double totalRadTransProb = 0.0;
|
||||
@@ -229,7 +222,7 @@ G4double G4AtomicTransitionManager::TotalRadiativeTransitionProbability(
|
||||
G4FluoTransition* transition = v[shellIndex];
|
||||
G4DataVector transProb = transition->TransitionProbabilities();
|
||||
|
||||
for (size_t j=0; j<transProb.size(); ++j)
|
||||
for (std::size_t j=0; j<transProb.size(); ++j)
|
||||
{
|
||||
totalRadTransProb += transProb[j];
|
||||
}
|
||||
@@ -258,7 +251,7 @@ G4double G4AtomicTransitionManager::TotalRadiativeTransitionProbability(
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
G4double G4AtomicTransitionManager::TotalNonRadiativeTransitionProbability(
|
||||
G4int Z, size_t shellIndex) const
|
||||
G4int Z, std::size_t shellIndex) const
|
||||
{
|
||||
G4double prob = 1.0 - TotalRadiativeTransitionProbability(Z, shellIndex);
|
||||
if(prob > 1.0 || prob < 0.0) {
|
||||
|
||||
@@ -160,7 +160,7 @@ G4double G4FluoData::StartShellEnergy(G4int initIndex, G4int vacancyIndex) const
|
||||
if (pos != energyMap.end())
|
||||
{
|
||||
G4DataVector dataSet = *((*pos).second);
|
||||
|
||||
|
||||
G4int nData = (G4int)dataSet.size();
|
||||
if (initIndex >= 0 && initIndex < nData)
|
||||
{
|
||||
@@ -189,7 +189,7 @@ G4double G4FluoData::StartShellProb(G4int initIndex, G4int vacancyIndex) const
|
||||
if (pos != probabilityMap.end())
|
||||
{
|
||||
G4DataVector dataSet = *((*pos).second);
|
||||
|
||||
|
||||
G4int nData = (G4int)dataSet.size();
|
||||
if (initIndex >= 0 && initIndex < nData)
|
||||
{
|
||||
|
||||
@@ -46,7 +46,6 @@
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4VAtomDeexcitation.hh"
|
||||
#include "G4EmParameters.hh"
|
||||
#include <thread>
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
@@ -69,7 +68,8 @@ namespace
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4LivermorePhotoElectricModel::G4LivermorePhotoElectricModel(const G4String& nam) : G4VEmModel(nam)
|
||||
G4LivermorePhotoElectricModel::G4LivermorePhotoElectricModel(const G4String& nam)
|
||||
: G4VEmModel(nam)
|
||||
{
|
||||
verboseLevel = 0;
|
||||
// Verbosity scale:
|
||||
@@ -95,6 +95,21 @@ G4LivermorePhotoElectricModel::G4LivermorePhotoElectricModel(const G4String& nam
|
||||
|
||||
// For water
|
||||
fSandiaCof.resize(4, 0.0);
|
||||
|
||||
FindDirectoryPath();
|
||||
|
||||
if (fCrossSection == nullptr) {
|
||||
fCrossSection = new G4ElementData(ZMAXPE);
|
||||
fCrossSection->SetName("PhotoEffXS");
|
||||
fCrossSectionLE = new G4ElementData(ZMAXPE);
|
||||
fCrossSectionLE->SetName("PhotoEffLowXS");
|
||||
for (G4int i = 0; i < ZMAXPE; ++i) {
|
||||
fParamHigh[i] = nullptr;
|
||||
fParamLow[i] = nullptr;
|
||||
fNShells[i] = 0;
|
||||
fNShellsUsed[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
@@ -103,14 +118,10 @@ G4LivermorePhotoElectricModel::~G4LivermorePhotoElectricModel()
|
||||
{
|
||||
if (isInitializer) {
|
||||
for (G4int i = 0; i < ZMAXPE; ++i) {
|
||||
if (fParamHigh[i]) {
|
||||
delete fParamHigh[i];
|
||||
fParamHigh[i] = nullptr;
|
||||
}
|
||||
if (fParamLow[i]) {
|
||||
delete fParamLow[i];
|
||||
fParamLow[i] = nullptr;
|
||||
}
|
||||
delete fParamHigh[i];
|
||||
fParamHigh[i] = nullptr;
|
||||
delete fParamLow[i];
|
||||
fParamLow[i] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,7 +140,6 @@ void G4LivermorePhotoElectricModel::Initialise(const G4ParticleDefinition*,
|
||||
|
||||
if (isInitializer) {
|
||||
G4AutoLock l(&livPhotoeffMutex);
|
||||
FindDirectoryPath();
|
||||
if (fWater == nullptr) {
|
||||
fWater = G4Material::GetMaterial("G4_WATER", false);
|
||||
if (fWater == nullptr) {
|
||||
@@ -140,13 +150,6 @@ void G4LivermorePhotoElectricModel::Initialise(const G4ParticleDefinition*,
|
||||
}
|
||||
}
|
||||
|
||||
if (fCrossSection == nullptr) {
|
||||
fCrossSection = new G4ElementData(ZMAXPE);
|
||||
fCrossSection->SetName("PhotoEffXS");
|
||||
fCrossSectionLE = new G4ElementData(ZMAXPE);
|
||||
fCrossSectionLE->SetName("PhotoEffLowXS");
|
||||
}
|
||||
|
||||
const G4ElementTable* elemTable = G4Element::GetElementTable();
|
||||
std::size_t numElems = (*elemTable).size();
|
||||
for (std::size_t ie = 0; ie < numElems; ++ie) {
|
||||
@@ -188,7 +191,8 @@ G4LivermorePhotoElectricModel::CrossSectionPerVolume(const G4Material* material,
|
||||
G4double, G4double)
|
||||
{
|
||||
fCurrSection = 0.0;
|
||||
if (fWater && (material == fWater || material->GetBaseMaterial() == fWater)) {
|
||||
if (nullptr != fWater &&
|
||||
(material == fWater || material->GetBaseMaterial() == fWater)) {
|
||||
if (energy <= fWaterEnergyLimit) {
|
||||
fWater->GetSandiaTable()->GetSandiaCofWater(energy, fSandiaCof);
|
||||
|
||||
@@ -475,7 +479,7 @@ void G4LivermorePhotoElectricModel::SampleSecondaries(std::vector<G4DynamicParti
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
const G4String& G4LivermorePhotoElectricModel::FindDirectoryPath()
|
||||
void G4LivermorePhotoElectricModel::FindDirectoryPath()
|
||||
{
|
||||
// no check in this method - environment variable is check by utility
|
||||
if (fDataDirectory.empty()) {
|
||||
@@ -489,7 +493,6 @@ const G4String& G4LivermorePhotoElectricModel::FindDirectoryPath()
|
||||
}
|
||||
fDataDirectory = ost.str();
|
||||
}
|
||||
return fDataDirectory;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
@@ -512,13 +515,13 @@ void G4LivermorePhotoElectricModel::ReadData(G4int Z)
|
||||
// spline for photoeffect total x-section above K-shell when using EPDL97
|
||||
// but below the parameterized ones
|
||||
|
||||
G4bool spline = (G4EmParameters::Instance()->LivermoreDataDir() == "livermore");
|
||||
G4int number = G4EmParameters::Instance()->NumberForFreeVector();
|
||||
auto pv = new G4PhysicsFreeVector(spline);
|
||||
auto param = G4EmParameters::Instance();
|
||||
G4bool spline = (param->LivermoreDataDir() == "livermore");
|
||||
G4int number = param->NumberForFreeVector();
|
||||
|
||||
// fDataDirectory will be defined after these lines
|
||||
std::ostringstream ost;
|
||||
ost << FindDirectoryPath() << "pe-cs-" << Z << ".dat";
|
||||
ost << fDataDirectory << "pe-cs-" << Z << ".dat";
|
||||
std::ifstream fin(ost.str().c_str());
|
||||
if (!fin.is_open()) {
|
||||
G4ExceptionDescription ed;
|
||||
@@ -532,6 +535,7 @@ void G4LivermorePhotoElectricModel::ReadData(G4int Z)
|
||||
G4cout << "File " << ost.str().c_str() << " is opened by G4LivermorePhotoElectricModel"
|
||||
<< G4endl;
|
||||
}
|
||||
auto pv = new G4PhysicsFreeVector(spline);
|
||||
pv->Retrieve(fin, true);
|
||||
pv->ScaleVector(MeV, barn);
|
||||
pv->FillSecondDerivatives();
|
||||
@@ -540,7 +544,6 @@ void G4LivermorePhotoElectricModel::ReadData(G4int Z)
|
||||
fin.close();
|
||||
|
||||
// read high-energy fit parameters
|
||||
fParamHigh[Z] = new std::vector<G4double>;
|
||||
G4int n1 = 0;
|
||||
G4int n2 = 0;
|
||||
G4double x;
|
||||
@@ -581,6 +584,7 @@ void G4LivermorePhotoElectricModel::ReadData(G4int Z)
|
||||
}
|
||||
|
||||
fNShells[Z] = n1;
|
||||
fParamHigh[Z] = new std::vector<G4double>;
|
||||
fParamHigh[Z]->reserve(7 * n1 + 1);
|
||||
fParamHigh[Z]->push_back(x * MeV);
|
||||
for (G4int i = 0; i < n1; ++i) {
|
||||
@@ -598,7 +602,6 @@ void G4LivermorePhotoElectricModel::ReadData(G4int Z)
|
||||
fin1.close();
|
||||
|
||||
// read low-energy fit parameters
|
||||
fParamLow[Z] = new std::vector<G4double>;
|
||||
G4int n1_low = 0;
|
||||
G4int n2_low = 0;
|
||||
G4double x_low;
|
||||
@@ -639,6 +642,7 @@ void G4LivermorePhotoElectricModel::ReadData(G4int Z)
|
||||
}
|
||||
|
||||
fNShells[Z] = n1_low;
|
||||
fParamLow[Z] = new std::vector<G4double>;
|
||||
fParamLow[Z]->reserve(7 * n1_low + 1);
|
||||
fParamLow[Z]->push_back(x_low * MeV);
|
||||
for (G4int i = 0; i < n1_low; ++i) {
|
||||
@@ -706,6 +710,7 @@ void G4LivermorePhotoElectricModel::ReadData(G4int Z)
|
||||
<< G4endl;
|
||||
G4Exception("G4LivermorePhotoElectricModel::ReadData()", "em0003", FatalException, ed,
|
||||
"G4LEDATA version should be G4EMLOW8.0 or later.");
|
||||
delete pv1;
|
||||
return;
|
||||
}
|
||||
if (verboseLevel > 3) {
|
||||
@@ -744,20 +749,6 @@ G4double G4LivermorePhotoElectricModel::GetBindingEnergy(G4int Z, G4int shell)
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void
|
||||
G4LivermorePhotoElectricModel::InitialiseForElement(const G4ParticleDefinition*, G4int Z)
|
||||
{
|
||||
if (fCrossSection == nullptr) {
|
||||
fCrossSection = new G4ElementData(ZMAXPE);
|
||||
fCrossSection->SetName("PhotoEffXS");
|
||||
fCrossSectionLE = new G4ElementData(ZMAXPE);
|
||||
fCrossSectionLE->SetName("PhotoEffLowXS");
|
||||
}
|
||||
ReadData(Z);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4LivermorePhotoElectricModel::InitialiseOnFly(G4int Z)
|
||||
{
|
||||
if (fCrossSection->GetElementData(Z) == nullptr && Z > 0 && Z < ZMAXPE) {
|
||||
|
||||
@@ -605,7 +605,7 @@ G4double G4PenelopeBremsstrahlungFS::SampleGammaEnergy(G4double energy,const G4M
|
||||
const G4double cut) const
|
||||
{
|
||||
std::pair<const G4Material*,G4double> theKey = std::make_pair(mat,cut);
|
||||
if (!(fSamplingTable->count(theKey)) || !(fPBcut->count(theKey)) ||
|
||||
if (!(fSamplingTable->count(theKey)) || !(fPBcut->count(theKey)) ||
|
||||
!(fReducedXSTable->count(theKey)))
|
||||
{
|
||||
G4ExceptionDescription ed;
|
||||
|
||||
@@ -257,7 +257,7 @@ G4double G4PenelopeBremsstrahlungModel::CrossSectionPerVolume(const G4Material*
|
||||
{
|
||||
G4cout << "G4PenelopeBremsstrahlungModel " << G4endl;
|
||||
G4cout << "Mean free path for gamma emission > " << cutEnergy/keV << " keV at " <<
|
||||
energy/keV << " keV = " <<
|
||||
energy/keV << " keV = " <<
|
||||
(crossPerVolume? (1./crossPerVolume)/mm : DBL_MAX) << " mm" << G4endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -236,7 +236,7 @@ G4double G4PenelopeComptonModel::CrossSectionPerVolume(const G4Material* materia
|
||||
|
||||
if (fVerboseLevel > 2)
|
||||
G4cout << "Compton mean free path at " << energy/keV << " keV for material " <<
|
||||
material->GetName() << " = " <<
|
||||
material->GetName() << " = " <<
|
||||
(csvolume ? (1./csvolume)/mm : DBL_MAX) << " mm" << G4endl;
|
||||
return csvolume;
|
||||
}
|
||||
|
||||
@@ -323,12 +323,12 @@ G4double G4PenelopeIonisationModel::CrossSectionPerVolume(const G4Material* mate
|
||||
{
|
||||
G4cout << "G4PenelopeIonisationModel " << G4endl;
|
||||
G4cout << "Mean free path for delta emission > " << cutEnergy/keV << " keV at " <<
|
||||
energy/keV << " keV = " <<
|
||||
energy/keV << " keV = " <<
|
||||
(crossPerVolume ? (1./crossPerVolume)/mm : DBL_MAX) << " mm" << G4endl;
|
||||
if (theXS)
|
||||
totalCross = (theXS->GetTotalCrossSection(energy))*moleculeDensity;
|
||||
G4cout << "Total free path for ionisation (no threshold) at " <<
|
||||
energy/keV << " keV = " <<
|
||||
energy/keV << " keV = " <<
|
||||
(totalCross ? (1./totalCross)/mm : DBL_MAX) << " mm" << G4endl;
|
||||
}
|
||||
return crossPerVolume;
|
||||
|
||||
@@ -108,7 +108,7 @@ const std::vector<G4double>& G4ShellData::ShellVector(G4int Z) const
|
||||
{
|
||||
if (Z < zMin || Z > zMax)
|
||||
G4Exception("G4ShellData::ShellVector()","de0001",JustWarning,"Z outside boundaries");
|
||||
auto pos = occupancyPdfMap.find(Z);
|
||||
auto pos = occupancyPdfMap.find(Z);
|
||||
std::vector<G4double>* dataSet = (*pos).second;
|
||||
return *dataSet;
|
||||
}
|
||||
@@ -200,12 +200,12 @@ void G4ShellData::PrintData() const
|
||||
G4int id = (G4int) (*ids)[i];
|
||||
G4double e = (*energies)[i] / keV;
|
||||
G4cout << i << ") ";
|
||||
|
||||
if (occupancyData)
|
||||
|
||||
if (occupancyData)
|
||||
{
|
||||
G4cout << " Occupancy: ";
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
G4cout << " Shell id: ";
|
||||
}
|
||||
@@ -213,7 +213,7 @@ void G4ShellData::PrintData() const
|
||||
<< e << " keV ";
|
||||
if (occupancyData)
|
||||
{
|
||||
auto posOcc = occupancyPdfMap.find(Z);
|
||||
auto posOcc = occupancyPdfMap.find(Z);
|
||||
G4double prob = 0.;
|
||||
if (posOcc != occupancyPdfMap.end())
|
||||
{
|
||||
|
||||
@@ -241,7 +241,7 @@ G4double G4hIonEffChargeSquare::IonEffChargeSquare(
|
||||
} else {
|
||||
|
||||
// v1 is ion velocity in vF unit
|
||||
G4double v1{0.0}, v2{0.0};
|
||||
G4double v1{0.01}, v2{0.0};
|
||||
if (vF > 0.0) {
|
||||
v1 = std::sqrt( reducedEnergy / (25.0 * keV) )/ vF;
|
||||
v2 = 1.0/ (vF*vF);
|
||||
|
||||
@@ -6,9 +6,14 @@ It must **not** be used as a substitute for writing good git commit messages!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 2025-05-12 V.Ivanchenko (emmuons-V11-03-00)
|
||||
- G4RiGeMuPairProductionModel, G4RiGeAngularGenerator - G.Depaola & R.Pacheco
|
||||
provided fixes to the angular distribution of electrons and positrons.
|
||||
- G4MuPairProduction - enable RiGe model via G4EmParameters
|
||||
|
||||
## 2023-10-31 V.Ivanchenko (emmuons-V11-01-04)
|
||||
- G4RiGeMuPairProductionModel, G4RiGeAngularGenerator - a new 5D model for e+e-
|
||||
pair production by muons
|
||||
pair production by muons (authors G.Depaola & R.Pacheco)
|
||||
- fixed declaration of virtual destructors in several header files
|
||||
- G4MuPairProductionModel - minor clean-up for better code readability
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
//
|
||||
// File name: G4RiGeAngularGenerator
|
||||
//
|
||||
// Authors: Girardo Depaola & Ricardo Pacheco
|
||||
// Authors: Gerardo Depaola & Ricardo Pacheco
|
||||
//
|
||||
// Creation date: 29 October 2024
|
||||
//
|
||||
@@ -59,15 +59,15 @@ public:
|
||||
G4double gEnergy, G4int Z,
|
||||
const G4Material* mat = nullptr) override;
|
||||
|
||||
G4LorentzVector Sample5DPairDirections(const G4DynamicParticle* dp,
|
||||
G4ThreeVector& dirElectron,
|
||||
G4ThreeVector& dirPositron,
|
||||
const G4double gEnergy, const G4double q2,
|
||||
const G4double gMomentum,
|
||||
G4double muFinalMomentum,
|
||||
G4double muFinalEnergy,
|
||||
const G4double* randNumbs,
|
||||
const G4double* W);
|
||||
void Sample5DPairDirections(const G4DynamicParticle* dp,
|
||||
G4ThreeVector& dirElectron,
|
||||
G4ThreeVector& dirPositron,
|
||||
const G4double gEnergy, const G4double q2,
|
||||
const G4double gMomentum,
|
||||
G4double muFinalMomentum,
|
||||
G4double muFinalEnergy,
|
||||
const G4double* randNumbs,
|
||||
const G4double* W);
|
||||
|
||||
void PhiRotation(G4ThreeVector& dir, G4double phi);
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
#include "G4Positron.hh"
|
||||
#include "G4VEmModel.hh"
|
||||
#include "G4MuPairProductionModel.hh"
|
||||
#include "G4RiGeMuPairProductionModel.hh"
|
||||
#include "G4ElementData.hh"
|
||||
#include "G4EmParameters.hh"
|
||||
|
||||
@@ -113,18 +114,22 @@ void G4MuPairProduction::InitialiseEnergyLossProcess(
|
||||
isInitialised = true;
|
||||
|
||||
theParticle = part;
|
||||
G4EmParameters* param = G4EmParameters::Instance();
|
||||
|
||||
G4VEmModel* mod = EmModel(0);
|
||||
if(nullptr == mod) {
|
||||
if (nullptr == mod) {
|
||||
lowestKinEnergy = std::max(lowestKinEnergy, part->GetPDGMass()*8.0);
|
||||
auto ptr = new G4MuPairProductionModel(part);
|
||||
ptr->SetLowestKineticEnergy(lowestKinEnergy);
|
||||
mod = ptr;
|
||||
if (param->UseRiGePairProductionModel()) {
|
||||
mod = new G4MuPairProductionModel(part);
|
||||
} else {
|
||||
auto ptr = new G4MuPairProductionModel(part);
|
||||
ptr->SetLowestKineticEnergy(lowestKinEnergy);
|
||||
mod = ptr;
|
||||
}
|
||||
SetEmModel(mod);
|
||||
}
|
||||
|
||||
G4VEmFluctuationModel* fm = nullptr;
|
||||
G4EmParameters* param = G4EmParameters::Instance();
|
||||
mod->SetLowEnergyLimit(param->MinKinEnergy());
|
||||
mod->SetHighEnergyLimit(param->MaxKinEnergy());
|
||||
mod->SetSecondaryThreshold(param->MuHadBremsstrahlungTh());
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
//
|
||||
// File name: G4RiGeAngularGenerator
|
||||
//
|
||||
// Authors: Girardo Depaola & Ricardo Pacheco
|
||||
// Authors: Gerardo Depaola & Ricardo Pacheco
|
||||
//
|
||||
// Creation date: 27 October 2024
|
||||
//
|
||||
@@ -85,8 +85,7 @@ G4double G4RiGeAngularGenerator::SampleCosTheta(G4double primKinEnergy,
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4LorentzVector
|
||||
G4RiGeAngularGenerator::Sample5DPairDirections(const G4DynamicParticle* dp,
|
||||
void G4RiGeAngularGenerator::Sample5DPairDirections(const G4DynamicParticle* dp,
|
||||
G4ThreeVector& dirElectron,
|
||||
G4ThreeVector& dirPositron,
|
||||
const G4double gEnergy, const G4double q2,
|
||||
@@ -96,10 +95,9 @@ G4RiGeAngularGenerator::Sample5DPairDirections(const G4DynamicParticle* dp,
|
||||
const G4double* randNumbs,
|
||||
const G4double* W)
|
||||
{
|
||||
G4double muEnergy = dp->GetKineticEnergy();
|
||||
G4double muKinEnergy = dp->GetKineticEnergy();
|
||||
G4ThreeVector muMomentumVector = dp->GetMomentum();
|
||||
G4double muMomentum = muMomentumVector.mag();
|
||||
G4LorentzVector muFinalFourMomentum(muEnergy, muMomentumVector);
|
||||
|
||||
// Electron mass
|
||||
G4double eMass = CLHEP::electron_mass_c2;
|
||||
@@ -108,6 +106,9 @@ G4RiGeAngularGenerator::Sample5DPairDirections(const G4DynamicParticle* dp,
|
||||
// Muon mass
|
||||
G4double muMass = dp->GetDefinition()->GetPDGMass();
|
||||
|
||||
G4double muEnergy = muKinEnergy + muMass;
|
||||
G4LorentzVector muFinalFourMomentum(muMomentumVector, muEnergy);
|
||||
|
||||
G4double mint3 = 0.;
|
||||
G4double maxt3 = CLHEP::pi;
|
||||
G4double Cmin = std::cos(maxt3);
|
||||
@@ -126,20 +127,7 @@ G4RiGeAngularGenerator::Sample5DPairDirections(const G4DynamicParticle* dp,
|
||||
|
||||
G4ThreeVector dirGamma;
|
||||
dirGamma.set(sintg*cospg, sintg*sinpg, costg);
|
||||
G4LorentzVector gFourMomentum(gEnergy, dirGamma*gMomentum);
|
||||
|
||||
G4double Ap = muMomentum*muMomentum + muFinalMomentum*muFinalMomentum + gMomentum*gMomentum;
|
||||
G4double A = Ap - 2.*muMomentum*gMomentum*costg;
|
||||
G4double B = 2.*muFinalMomentum*gMomentum*sintg*cospg;
|
||||
G4double C = 2.*muFinalMomentum*gMomentum*costg - 2.*muMomentum*muFinalMomentum;
|
||||
G4double absB = std::abs(B);
|
||||
G4double t1interval = (1./(A + C + absB*mint3) - 1./(A + C + absB*maxt3))/absB;
|
||||
G4double t1 = (-(A + C) + 1./(1./(A + C + absB*mint3) - absB*t1interval*randNumbs[0]))/absB;
|
||||
G4double sint1 = std::sin(t1);
|
||||
G4double cost1 = std::cos(t1);
|
||||
|
||||
G4ThreeVector dirMuon;
|
||||
dirMuon.set(sint1, 0., cost1);
|
||||
G4LorentzVector gFourMomentum(dirGamma*gMomentum, gEnergy);
|
||||
|
||||
G4double cost5 = -1. + 2.*randNumbs[6];
|
||||
G4double phi5 = CLHEP::twopi*randNumbs[8];
|
||||
@@ -187,10 +175,7 @@ G4RiGeAngularGenerator::Sample5DPairDirections(const G4DynamicParticle* dp,
|
||||
|
||||
G4ThreeVector dirGamma;
|
||||
dirGamma.set(sint*cosp, sint*sinp, cost);
|
||||
G4LorentzVector gFourMomentum(gEnergy, dirGamma*gMomentum);
|
||||
|
||||
G4ThreeVector dirMuon;
|
||||
dirMuon.set(sint3, 0., cost3);
|
||||
G4LorentzVector gFourMomentum(dirGamma*gMomentum, gEnergy);
|
||||
|
||||
G4double cost5 = -1. + 2.*randNumbs[6];
|
||||
G4double phi5 = CLHEP::twopi*randNumbs[8];
|
||||
@@ -233,17 +218,18 @@ G4RiGeAngularGenerator::Sample5DPairDirections(const G4DynamicParticle* dp,
|
||||
G4double pEnergy = muEnergy - muFEnergy - eEnergy;
|
||||
G4double pMomentum = std::sqrt(pEnergy*pEnergy - eMass*eMass);
|
||||
|
||||
G4double A3 = -2.*muMass*muMass + 2.*muEnergy*muFinalEnergy;
|
||||
G4double B3 = -2.*muMomentum*muFinalMomentum;
|
||||
G4double A3 = -2.*muMass*muMass + 2.*muEnergy*muFEnergy;
|
||||
G4double B3 = -2.*std::sqrt(muEnergy*muEnergy - muMass*muMass)*muFMomentum;
|
||||
G4double cost3interval = G4Log((A3 + B3*Cmax)/(A3 + B3*Cmin))/B3;
|
||||
|
||||
G4double expanCost3r6 = G4Exp(B3*cost3interval*randNumbs[5]);
|
||||
G4double cost3 = A3*(expanCost3r6 - 1.)/B3 + Cmin*expanCost3r6;
|
||||
G4double sint3 = std::sqrt((1. - cost3)*(1. + cost3));
|
||||
|
||||
G4ThreeVector muFinalMomentumVector(muFMomentum*sint3, 0., muFMomentum*cost3);
|
||||
|
||||
G4LorentzVector muFourMomentum(muMomentum, muMomentumVector);
|
||||
muFinalFourMomentum.set(muFEnergy, muFinalMomentumVector);
|
||||
G4LorentzVector muFourMomentum(muMomentumVector, muEnergy);
|
||||
muFinalFourMomentum.set(muFinalMomentumVector, muFEnergy);
|
||||
G4LorentzVector auxVec1 = muFourMomentum - muFinalFourMomentum;
|
||||
G4double A5 = auxVec1.mag2() - 2.*eEnergy*(muEnergy - muFEnergy) +
|
||||
2.*muMomentumVector[2]*eMomentum - 2.*muFMomentum*eMomentum*cost3;
|
||||
@@ -308,9 +294,10 @@ G4RiGeAngularGenerator::Sample5DPairDirections(const G4DynamicParticle* dp,
|
||||
G4double eEnergy = muEnergy - muFEnergy - pEnergy;
|
||||
G4double eMomentum = std::sqrt(eEnergy*eEnergy - eMass*eMass);
|
||||
|
||||
G4double A3 = -2.*muMass*muMass + 2.*muEnergy*muFinalEnergy;
|
||||
G4double B3 = -2.*muMomentum*muFMomentum;
|
||||
G4double A3 = -2.*muMass*muMass + 2.*muEnergy*muFEnergy;
|
||||
G4double B3 = -2.*std::sqrt(muEnergy*muEnergy - muMass*muMass)*muFMomentum;
|
||||
G4double cost3interval = G4Log((A3 + B3*Cmax)/(A3 + B3*Cmin))/B3;
|
||||
|
||||
G4double expanCost3r6 = G4Exp(B3*cost3interval*randNumbs[5]);
|
||||
G4double cost3 = A3*(expanCost3r6 - 1.)/B3 + Cmin*expanCost3r6;
|
||||
G4double sint3 = std::sqrt((1. - cost3)*(1. + cost3));
|
||||
@@ -319,8 +306,8 @@ G4RiGeAngularGenerator::Sample5DPairDirections(const G4DynamicParticle* dp,
|
||||
muFinalMomentumVector.set(muFMomentum*sint3*cosp3, muFMomentum*sint3*sinp3,
|
||||
muFMomentum*cost3);
|
||||
|
||||
G4LorentzVector muFourMomentum(muMomentum, muMomentumVector);
|
||||
muFinalFourMomentum.set(muFEnergy, muFinalMomentumVector);
|
||||
G4LorentzVector muFourMomentum(muMomentumVector, muEnergy);
|
||||
muFinalFourMomentum.set(muFinalMomentumVector, muFEnergy);
|
||||
G4LorentzVector auxVec1 = muFourMomentum - muFinalFourMomentum;
|
||||
G4double A6 = auxVec1.mag2() - 2.*pEnergy*(muEnergy - muFEnergy) +
|
||||
2.*muMomentumVector[2]*pMomentum - 2.*muFMomentum*pMomentum*cost3;
|
||||
@@ -360,7 +347,6 @@ G4RiGeAngularGenerator::Sample5DPairDirections(const G4DynamicParticle* dp,
|
||||
PhiRotation(dirElectron, phi3);
|
||||
PhiRotation(dirPositron, phi3);
|
||||
}
|
||||
return muFinalFourMomentum;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
@@ -395,7 +381,8 @@ G4LorentzVector G4RiGeAngularGenerator::eDP2(G4double x1, G4double x2,
|
||||
}
|
||||
|
||||
G4double QJM = std::sqrt(QJM2);
|
||||
G4LorentzVector x6(std::sqrt(x2 + QJM2), QJM*sint*cosp, QJM*sint*sinp, QJM*x4);
|
||||
|
||||
G4LorentzVector x6(QJM*sint*cosp, QJM*sint*sinp, QJM*x4, std::sqrt(x2 + QJM2));
|
||||
|
||||
return x6;
|
||||
}
|
||||
@@ -404,7 +391,7 @@ G4LorentzVector G4RiGeAngularGenerator::eDP2(G4double x1, G4double x2,
|
||||
|
||||
G4LorentzVector G4RiGeAngularGenerator::pDP2(G4double x3, const G4LorentzVector& x6)
|
||||
{
|
||||
G4LorentzVector x7(x3 + x6.vect().dot(x6.vect()), -x6.vect());
|
||||
G4LorentzVector x7(-x6.vect(), std::sqrt(x3 + x6.vect().dot(x6.vect())));
|
||||
return x7;
|
||||
}
|
||||
|
||||
|
||||
@@ -534,6 +534,7 @@ void G4RiGeMuPairProductionModel::SampleSecondaries(std::vector<G4DynamicParticl
|
||||
|
||||
// Energy and momentum of the pramary particle
|
||||
G4double kinEnergy = aDynamicParticle->GetKineticEnergy();
|
||||
G4double totEnergy = aDynamicParticle->GetTotalEnergy();
|
||||
G4double particleMomentum = aDynamicParticle->GetTotalMomentum();
|
||||
G4ThreeVector particleMomentumVector = aDynamicParticle->GetMomentum();
|
||||
G4ThreeVector partDirection = aDynamicParticle->GetMomentumDirection();
|
||||
@@ -660,7 +661,7 @@ void G4RiGeMuPairProductionModel::SampleSecondaries(std::vector<G4DynamicParticl
|
||||
|
||||
G4ThreeVector dirGamma;
|
||||
dirGamma.set(sintg*cospg, sintg*sinpg, costg);
|
||||
G4LorentzVector gFourMomentum(gEnergy, dirGamma*gMomentum);
|
||||
G4LorentzVector gFourMomentum(dirGamma*gMomentum, gEnergy);
|
||||
|
||||
G4double Ap = particleMomentum*particleMomentum +
|
||||
particleFinalMomentum*particleFinalMomentum + gMomentum*gMomentum;
|
||||
@@ -723,7 +724,7 @@ void G4RiGeMuPairProductionModel::SampleSecondaries(std::vector<G4DynamicParticl
|
||||
|
||||
G4ThreeVector dirGamma;
|
||||
dirGamma.set(sint*cosp, sint*sinp, cost);
|
||||
G4LorentzVector gFourMomentum(gEnergy, dirGamma*gMomentum);
|
||||
G4LorentzVector gFourMomentum(dirGamma*gMomentum, gEnergy);
|
||||
|
||||
// Ingoing parent particle change
|
||||
G4double Phi = CLHEP::twopi*randNumbs[3];
|
||||
@@ -779,8 +780,8 @@ void G4RiGeMuPairProductionModel::SampleSecondaries(std::vector<G4DynamicParticl
|
||||
G4ThreeVector muFinalMomentumVector;
|
||||
muFinalMomentumVector.set(particleFinalMomentum*sint3, 0., particleFinalMomentum*cost3);
|
||||
|
||||
G4LorentzVector muFourMomentum(particleMomentum, particleMomentumVector);
|
||||
G4LorentzVector muFinalFourMomentum(particleFinalEnergy, muFinalMomentumVector);
|
||||
G4LorentzVector muFourMomentum(particleMomentumVector, totEnergy);
|
||||
G4LorentzVector muFinalFourMomentum(muFinalMomentumVector, particleFinalEnergy);
|
||||
G4LorentzVector auxVec1 = muFourMomentum - muFinalFourMomentum;
|
||||
G4double A5 = auxVec1.mag2() - 2.*eEnergy*(kinEnergy - particleFinalEnergy) +
|
||||
2.*particleMomentumVector[2]*eMomentum - 2.*particleFinalMomentum*eMomentum*cost3;
|
||||
@@ -893,13 +894,14 @@ void G4RiGeMuPairProductionModel::SampleSecondaries(std::vector<G4DynamicParticl
|
||||
|
||||
eDirection.set(sint5*cosp5, sint5*sinp5, cost5);
|
||||
}
|
||||
|
||||
// these lines are closed temporary, will be enabled or removed after testing
|
||||
/*
|
||||
fAngularGenerator->Sample5DPairDirections(aDynamicParticle, eDirection, pDirection,
|
||||
gEnergy, Q2, gMomentum,
|
||||
particleFinalMomentum,
|
||||
particleFinalEnergy,
|
||||
randNumbs, W);
|
||||
|
||||
*/
|
||||
// create G4DynamicParticle object for e+e-
|
||||
auto aParticle1 = new G4DynamicParticle(theElectron, eDirection, eEnergy);
|
||||
auto aParticle2 = new G4DynamicParticle(thePositron, pDirection, pEnergy);
|
||||
|
||||
@@ -6,6 +6,10 @@ It must **not** be used as a substitute for writing good git commit messages!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 2025-02-13 Gabriele Cosmo (empii-V11-03-00)
|
||||
- Use "const G4String&" in G4hImpactIonisation::InitializeMe() to avoid
|
||||
unnecessary copy.
|
||||
|
||||
## 2023-08-29 Ben Morgan (empii-V11-01-00)
|
||||
- Fix Coverity warnings
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ void G4hImpactIonisation::InitializeMe()
|
||||
eMinPixe = 1.* keV;
|
||||
eMaxPixe = 200. * MeV;
|
||||
|
||||
G4String defaultPixeModel("ecpssr");
|
||||
const G4String& defaultPixeModel("ecpssr");
|
||||
modelK = defaultPixeModel;
|
||||
modelL = defaultPixeModel;
|
||||
modelM = defaultPixeModel;
|
||||
|
||||
@@ -6,10 +6,33 @@ It must **not** be used as a substitute for writing good git commit messages!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 2025-02-07 Igor Semeniouk (emstand-V11-02-22)
|
||||
## 2025-04-25 V.Ivanchenko (emstand-V11-03-06)
|
||||
- G4LowPAIH2O - fixed Coverity warnings
|
||||
|
||||
## 2025-04-23 V.Ivanchenko (emstand-V11-03-05)
|
||||
- G4UrbanMscModel - L.Urban propose a small change for Opt3 case, which may
|
||||
improve performance. Should not affect any result.
|
||||
|
||||
## 2025-03-12 V.Ivanchenko (emstand-V11-03-04)
|
||||
- G4LowPAIH2O - removed compilation warnings due to explicit types conversion
|
||||
problems reported by J.Allison
|
||||
|
||||
## 2025-03-11 V.Grichine (emstand-V11-03-03)
|
||||
- G4LowPAIH2O class with G4LowDataH2O.hh data file for dE/dx in water for p and e-.
|
||||
|
||||
## 2025-02-26 V.Ivanchenko (emstand-V11-03-02)
|
||||
- G4UrbanMscModel - L.Urban propose cosmetic change for Opt3 case and updated
|
||||
comments to the code. Should not affect any result.
|
||||
|
||||
## 2025-02-07 Igor Semeniouk (emstand-V11-03-01)
|
||||
- G4OrePowellAtRestModel - Add missing decay plane rotation
|
||||
( random x axis phi )
|
||||
|
||||
## 2025-01-19 V.Ivanchenko (emstand-V11-03-00)
|
||||
- G4eBremsstrahlungRelModel - This is a reversion of !4755 (merged just before the
|
||||
release 11.3). This implementation needed for EM design toward parallel
|
||||
initialisation of EM physics.
|
||||
|
||||
## 2024-11-08 V.Ivanchenko (emstand-V11-02-21)
|
||||
- G4BraggModel - fixed problem of 4.12 MeV mu+ range reported in
|
||||
the Forum #12312.
|
||||
|
||||
@@ -0,0 +1,554 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// G4LowDataH2O.hh -- header file
|
||||
//
|
||||
// GEANT 4 class header file --- Copyright CERN 1995
|
||||
// CERB Geneva Switzerland
|
||||
//
|
||||
// for information related to this code, please, contact
|
||||
// CERN, CN Division, ASD Group
|
||||
//
|
||||
// Preparation of ionizing collision cross section according to Photo Absorption
|
||||
// Ionization (PAI) model for simulation of ionization energy losses in very thin
|
||||
// layers of water for low energy protons and electrons.
|
||||
//
|
||||
// Author: Vladimir.Grichine@cern.ch
|
||||
//
|
||||
// History:
|
||||
//
|
||||
// 2.12.24, V. Grichine: 1st version
|
||||
|
||||
#ifndef G4LOWDATAH2O_HH
|
||||
#define G4LOWDATAH2O_HH
|
||||
|
||||
#include "G4LowPAIH2O.hh"
|
||||
|
||||
// The data array size
|
||||
|
||||
const G4int G4LowPAIH2O:: theBin = 1007;
|
||||
|
||||
/////////////////////////////////////////
|
||||
//
|
||||
// Transfer energies in Geant4 units (MeV)
|
||||
|
||||
const G4double G4LowPAIH2O::theEsum[1007] = {
|
||||
|
||||
1.00084e-07, 1.00315e-07, 1.00778e-07, 1.01243e-07, 1.01711e-07, 1.01945e-07,
|
||||
1.02416e-07, 1.02888e-07, 1.03363e-07, 1.0384e-07, 1.0408e-07, 1.0456e-07,
|
||||
1.05043e-07, 1.05528e-07, 1.06015e-07, 1.06504e-07, 1.06996e-07, 1.07242e-07,
|
||||
1.07737e-07, 1.08235e-07, 1.08734e-07, 1.09348e-07, 1.0974e-07, 1.10247e-07,
|
||||
1.10756e-07, 1.11267e-07, 1.11781e-07, 1.12296e-07, 1.12815e-07, 1.13336e-07,
|
||||
1.13859e-07, 1.14384e-07, 1.14912e-07, 1.15443e-07, 1.15975e-07, 1.16511e-07,
|
||||
1.17049e-07, 1.17589e-07, 1.18132e-07, 1.18677e-07, 1.19225e-07, 1.19775e-07,
|
||||
1.20328e-07, 1.20883e-07, 1.21441e-07, 1.22283e-07, 1.22786e-07, 1.23414e-07,
|
||||
1.23984e-07, 1.24557e-07, 1.25131e-07, 1.25999e-07, 1.2658e-07, 1.27165e-07,
|
||||
1.27752e-07, 1.28341e-07, 1.29231e-07, 1.29827e-07, 1.30427e-07, 1.31331e-07,
|
||||
1.31937e-07, 1.32546e-07, 1.33465e-07, 1.34081e-07, 1.347e-07, 1.35633e-07,
|
||||
1.36259e-07, 1.36888e-07, 1.37837e-07, 1.38473e-07, 1.39433e-07, 1.40077e-07,
|
||||
1.41048e-07, 1.41699e-07, 1.42353e-07, 1.4334e-07, 1.44333e-07, 1.44999e-07,
|
||||
1.46005e-07, 1.46678e-07, 1.47695e-07, 1.48377e-07, 1.49405e-07, 1.5044e-07,
|
||||
1.51135e-07, 1.52183e-07, 1.53238e-07, 1.53945e-07, 1.55012e-07, 1.56087e-07,
|
||||
1.56807e-07, 1.57894e-07, 1.58989e-07, 1.60091e-07, 1.61201e-07, 1.61945e-07,
|
||||
1.63067e-07, 1.64197e-07, 1.65336e-07, 1.66482e-07, 1.67636e-07, 1.68798e-07,
|
||||
1.69968e-07, 1.71146e-07, 1.72332e-07, 1.73527e-07, 1.74729e-07, 1.75941e-07,
|
||||
1.7716e-07, 1.78388e-07, 1.79625e-07, 1.8087e-07, 1.82124e-07, 1.83809e-07,
|
||||
1.85083e-07, 1.86366e-07, 1.87658e-07, 1.89394e-07, 1.90707e-07, 1.92029e-07,
|
||||
1.93806e-07, 1.95149e-07, 1.96955e-07, 1.9832e-07, 2.00155e-07, 2.01542e-07,
|
||||
2.03407e-07, 2.04817e-07, 2.06712e-07, 2.08145e-07, 2.10071e-07, 2.12015e-07,
|
||||
2.13977e-07, 2.1546e-07, 2.17453e-07, 2.19466e-07, 2.21496e-07, 2.23546e-07,
|
||||
2.25614e-07, 2.27702e-07, 2.29809e-07, 2.31935e-07, 2.34081e-07, 2.36248e-07,
|
||||
2.38433e-07, 2.40639e-07, 2.42866e-07, 2.45678e-07, 2.47951e-07, 2.50245e-07,
|
||||
2.53143e-07, 2.55485e-07, 2.58444e-07, 2.60835e-07, 2.63856e-07, 2.66911e-07,
|
||||
2.69381e-07, 2.725e-07, 2.75655e-07, 2.78847e-07, 2.82076e-07, 2.85342e-07,
|
||||
2.88646e-07, 2.91989e-07, 2.9537e-07, 2.9879e-07, 3.0225e-07, 3.06455e-07,
|
||||
3.10003e-07, 3.13593e-07, 3.17956e-07, 3.22379e-07, 3.26112e-07, 3.30648e-07,
|
||||
3.35248e-07, 3.39912e-07, 3.44641e-07, 3.49435e-07, 3.54296e-07, 3.59225e-07,
|
||||
3.65062e-07, 3.7014e-07, 3.75289e-07, 3.81387e-07, 3.87584e-07, 3.93882e-07,
|
||||
4.00282e-07, 4.06786e-07, 4.13396e-07, 4.15304e-07, 4.16262e-07, 4.18183e-07,
|
||||
4.19147e-07, 4.20113e-07, 4.22052e-07, 4.23025e-07, 4.24e-07, 4.24978e-07,
|
||||
4.2694e-07, 4.27924e-07, 4.2891e-07, 4.29899e-07, 4.31883e-07, 4.32879e-07,
|
||||
4.33877e-07, 4.34877e-07, 4.36884e-07, 4.37891e-07, 4.38901e-07, 4.39912e-07,
|
||||
4.40927e-07, 4.42962e-07, 4.43983e-07, 4.45006e-07, 4.46032e-07, 4.48091e-07,
|
||||
4.49124e-07, 4.50159e-07, 4.51197e-07, 4.52237e-07, 4.54325e-07, 4.55372e-07,
|
||||
4.56422e-07, 4.57474e-07, 4.58528e-07, 4.59585e-07, 4.61707e-07, 4.62771e-07,
|
||||
4.63838e-07, 4.64907e-07, 4.65979e-07, 4.67053e-07, 4.6813e-07, 4.70291e-07,
|
||||
4.71375e-07, 4.72461e-07, 4.7355e-07, 4.74642e-07, 4.75736e-07, 4.77932e-07,
|
||||
4.79034e-07, 4.80138e-07, 4.81245e-07, 4.82355e-07, 4.83467e-07, 4.85698e-07,
|
||||
4.8794e-07, 4.90192e-07, 4.92455e-07, 4.9359e-07, 4.95868e-07, 4.98157e-07,
|
||||
5.00456e-07, 5.0161e-07, 5.03926e-07, 5.06251e-07, 5.08588e-07, 5.09761e-07,
|
||||
5.12114e-07, 5.14477e-07, 5.16852e-07, 5.19238e-07, 5.20435e-07, 5.22837e-07,
|
||||
5.2525e-07, 5.27675e-07, 5.3011e-07, 5.32557e-07, 5.35015e-07, 5.36249e-07,
|
||||
5.38724e-07, 5.41211e-07, 5.43709e-07, 5.46218e-07, 5.4874e-07, 5.51273e-07,
|
||||
5.53817e-07, 5.53894e-07, 5.58941e-07, 5.61521e-07, 5.64113e-07, 5.66717e-07,
|
||||
5.69333e-07, 5.71961e-07, 5.74601e-07, 5.77253e-07, 5.79918e-07, 5.82594e-07,
|
||||
5.85284e-07, 5.87985e-07, 5.90699e-07, 5.93426e-07, 5.96165e-07, 5.98917e-07,
|
||||
6.01681e-07, 6.04458e-07, 6.07248e-07, 6.11458e-07, 6.1428e-07, 6.17115e-07,
|
||||
6.19964e-07, 6.22825e-07, 6.257e-07, 6.30037e-07, 6.32945e-07, 6.35867e-07,
|
||||
6.38802e-07, 6.41751e-07, 6.46199e-07, 6.49182e-07, 6.52178e-07, 6.56699e-07,
|
||||
6.5973e-07, 6.62775e-07, 6.65835e-07, 6.7045e-07, 6.73545e-07, 6.78213e-07,
|
||||
6.81344e-07, 6.84489e-07, 6.89233e-07, 6.92415e-07, 6.97214e-07, 7.00433e-07,
|
||||
7.03666e-07, 7.08543e-07, 7.11814e-07, 7.16748e-07, 7.20056e-07, 7.25047e-07,
|
||||
7.30073e-07, 7.33443e-07, 7.38527e-07, 7.41936e-07, 7.47079e-07, 7.52257e-07,
|
||||
7.55729e-07, 7.60968e-07, 7.6448e-07, 7.69779e-07, 7.75115e-07, 7.80488e-07,
|
||||
7.84091e-07, 7.89526e-07, 7.94999e-07, 8.00509e-07, 8.04204e-07, 8.09779e-07,
|
||||
8.15392e-07, 8.21044e-07, 8.26735e-07, 8.32465e-07, 8.38236e-07, 8.44046e-07,
|
||||
8.49897e-07, 8.55788e-07, 8.6172e-07, 8.67694e-07, 8.73708e-07, 8.79764e-07,
|
||||
8.85862e-07, 8.92003e-07, 8.98186e-07, 9.04412e-07, 9.10681e-07, 9.19108e-07,
|
||||
9.25478e-07, 9.31894e-07, 9.38353e-07, 9.47036e-07, 9.536e-07, 9.6021e-07,
|
||||
9.69095e-07, 9.75812e-07, 9.84842e-07, 9.91668e-07, 1.00084e-06, 1.00778e-06,
|
||||
1.01711e-06, 1.02416e-06, 1.03363e-06, 1.0408e-06, 1.05043e-06, 1.06015e-06,
|
||||
1.06996e-06, 1.07737e-06, 1.08734e-06, 1.0974e-06, 1.10756e-06, 1.11781e-06,
|
||||
1.12815e-06, 1.13859e-06, 1.14912e-06, 1.15976e-06, 1.17049e-06, 1.18132e-06,
|
||||
1.19225e-06, 1.20328e-06, 1.21441e-06, 1.22847e-06, 1.23984e-06, 1.24557e-06,
|
||||
1.25131e-06, 1.25999e-06, 1.2658e-06, 1.27165e-06, 1.27752e-06, 1.28341e-06,
|
||||
1.29231e-06, 1.29827e-06, 1.30427e-06, 1.31331e-06, 1.31937e-06, 1.32546e-06,
|
||||
1.33465e-06, 1.34081e-06, 1.347e-06, 1.35633e-06, 1.36259e-06, 1.36888e-06,
|
||||
1.37837e-06, 1.38473e-06, 1.39433e-06, 1.40077e-06, 1.41048e-06, 1.41699e-06,
|
||||
1.42353e-06, 1.4334e-06, 1.44333e-06, 1.44999e-06, 1.46004e-06, 1.46678e-06,
|
||||
1.47695e-06, 1.48377e-06, 1.49405e-06, 1.50441e-06, 1.51129e-06, 1.52183e-06,
|
||||
1.53238e-06, 1.53945e-06, 1.55012e-06, 1.56087e-06, 1.56807e-06, 1.57894e-06,
|
||||
1.58989e-06, 1.60091e-06, 1.612e-06, 1.61945e-06, 1.63067e-06, 1.64197e-06,
|
||||
1.65336e-06, 1.66482e-06, 1.67636e-06, 1.68798e-06, 1.69968e-06, 1.71146e-06,
|
||||
1.72332e-06, 1.73527e-06, 1.7473e-06, 1.75941e-06, 1.7716e-06, 1.78388e-06,
|
||||
1.79625e-06, 1.8087e-06, 1.82124e-06, 1.83809e-06, 1.85083e-06, 1.86366e-06,
|
||||
1.87658e-06, 1.89394e-06, 1.90707e-06, 1.92029e-06, 1.93806e-06, 1.95149e-06,
|
||||
1.96955e-06, 1.9832e-06, 2.00155e-06, 2.01542e-06, 2.03407e-06, 2.04817e-06,
|
||||
2.06712e-06, 2.08145e-06, 2.10071e-06, 2.12015e-06, 2.13977e-06, 2.1546e-06,
|
||||
2.17447e-06, 2.19465e-06, 2.21496e-06, 2.23546e-06, 2.25614e-06, 2.27702e-06,
|
||||
2.29809e-06, 2.31935e-06, 2.34081e-06, 2.36247e-06, 2.38433e-06, 2.40639e-06,
|
||||
2.42866e-06, 2.45678e-06, 2.47951e-06, 2.50245e-06, 2.53143e-06, 2.55485e-06,
|
||||
2.58444e-06, 2.60835e-06, 2.63856e-06, 2.66911e-06, 2.69381e-06, 2.725e-06,
|
||||
2.75655e-06, 2.78847e-06, 2.82076e-06, 2.85342e-06, 2.88646e-06, 2.91989e-06,
|
||||
2.9537e-06, 2.9879e-06, 3.0225e-06, 3.06455e-06, 3.10003e-06, 3.13593e-06,
|
||||
3.17955e-06, 3.22379e-06, 3.26112e-06, 3.30648e-06, 3.35248e-06, 3.39912e-06,
|
||||
3.4464e-06, 3.49435e-06, 3.54296e-06, 3.59225e-06, 3.65062e-06, 3.7014e-06,
|
||||
3.75289e-06, 3.81387e-06, 3.87584e-06, 3.93882e-06, 4.00282e-06, 4.06786e-06,
|
||||
4.13396e-06, 4.20113e-06, 4.27924e-06, 4.34877e-06, 4.42962e-06, 4.51197e-06,
|
||||
4.59585e-06, 4.6813e-06, 4.76833e-06, 4.85698e-06, 4.95868e-06, 5.06252e-06,
|
||||
5.16852e-06, 5.27669e-06, 5.38724e-06, 5.51272e-06, 5.64113e-06, 5.77253e-06,
|
||||
5.90699e-06, 6.04458e-06, 6.19964e-06, 6.35867e-06, 6.52178e-06, 6.7045e-06,
|
||||
6.89233e-06, 7.08543e-06, 7.11814e-06, 7.20056e-06, 7.30073e-06, 7.38527e-06,
|
||||
7.47079e-06, 7.55729e-06, 7.6448e-06, 7.75115e-06, 7.84091e-06, 7.94999e-06,
|
||||
8.04204e-06, 8.15392e-06, 8.26735e-06, 8.38236e-06, 8.49897e-06, 8.6172e-06,
|
||||
8.73708e-06, 8.85863e-06, 8.98186e-06, 9.10681e-06, 9.25478e-06, 9.38353e-06,
|
||||
9.536e-06, 9.69095e-06, 9.84841e-06, 1.00084e-05, 1.01711e-05, 1.03363e-05,
|
||||
1.05043e-05, 1.06996e-05, 1.08734e-05, 1.10756e-05, 1.12815e-05, 1.14912e-05,
|
||||
1.17049e-05, 1.19225e-05, 1.21441e-05, 1.23984e-05, 1.2658e-05, 1.29231e-05,
|
||||
1.31937e-05, 1.347e-05, 1.37837e-05, 1.41048e-05, 1.44333e-05, 1.47695e-05,
|
||||
1.51135e-05, 1.55012e-05, 1.58989e-05, 1.63067e-05, 1.67636e-05, 1.72332e-05,
|
||||
1.7654e-05, 1.82124e-05, 1.87658e-05, 1.93806e-05, 2.00155e-05, 2.06712e-05,
|
||||
2.13977e-05, 2.18265e-05, 2.24077e-05, 2.30044e-05, 2.3617e-05, 2.42459e-05,
|
||||
2.48915e-05, 2.55543e-05, 2.62348e-05, 2.69334e-05, 2.76507e-05, 2.8387e-05,
|
||||
2.91429e-05, 2.99189e-05, 3.07157e-05, 3.15336e-05, 3.23733e-05, 3.32354e-05,
|
||||
3.41204e-05, 3.5029e-05, 3.59618e-05, 3.69194e-05, 3.79025e-05, 3.89119e-05,
|
||||
3.99481e-05, 4.10118e-05, 4.21039e-05, 4.32251e-05, 4.43762e-05, 4.55579e-05,
|
||||
4.6771e-05, 4.80165e-05, 4.92951e-05, 5.06078e-05, 5.19555e-05, 5.3339e-05,
|
||||
5.47594e-05, 5.62176e-05, 5.77146e-05, 5.92515e-05, 6.08293e-05, 6.24491e-05,
|
||||
6.41121e-05, 6.58193e-05, 6.75721e-05, 6.93714e-05, 7.12187e-05, 7.31152e-05,
|
||||
7.50622e-05, 7.70611e-05, 7.91131e-05, 8.12198e-05, 8.33827e-05, 8.56031e-05,
|
||||
8.78826e-05, 9.02228e-05, 9.26254e-05, 9.50919e-05, 9.76241e-05, 0.000100224,
|
||||
0.000102893, 0.000105633, 0.000108445, 0.000111333, 0.000114298, 0.000117342,
|
||||
0.000120466, 0.000123674, 0.000126968, 0.000130349, 0.00013382, 0.000137383,
|
||||
0.000141042, 0.000144797, 0.000148653, 0.000152612, 0.000156676, 0.000160848,
|
||||
0.000165131, 0.000169528, 0.000174043, 0.000178677, 0.000183435, 0.00018832,
|
||||
0.000193335, 0.000198483, 0.000203769, 0.000209195, 0.000214765, 0.000220484,
|
||||
0.000226356, 0.000232383, 0.000238572, 0.000244925, 0.000251447, 0.000258143,
|
||||
0.000265017, 0.000272074, 0.000279319, 0.000286757, 0.000294393, 0.000302232,
|
||||
0.000310281, 0.000318543, 0.000327026, 0.000335734, 0.000344674, 0.000353853,
|
||||
0.000363275, 0.000372949, 0.00038288, 0.000393076, 0.000403544, 0.00041429,
|
||||
0.000425322, 0.000436648, 0.000448275, 0.000460212, 0.000472467, 0.000485049,
|
||||
0.000497965, 0.000511226, 0.000524839, 0.000538815, 0.000553163, 0.000567894,
|
||||
0.000583016, 0.000598541, 0.00061448, 0.000630843, 0.000647642, 0.000664888,
|
||||
0.000682593, 0.00070077, 0.000719431, 0.000738589, 0.000758257, 0.000778448,
|
||||
0.000799178, 0.000820459, 0.000842307, 0.000864737, 0.000887764, 0.000911405,
|
||||
0.000935675, 0.000960591, 0.000986171, 0.00101243, 0.00103939, 0.00106707,
|
||||
0.00109548, 0.00112466, 0.0011546, 0.00118535, 0.00121692, 0.00124932,
|
||||
0.00128259, 0.00131674, 0.00135181, 0.0013878, 0.00142476, 0.0014627, 0.00150165,
|
||||
0.00154164, 0.00158269, 0.00162484, 0.00166811, 0.00171253, 0.00175813,
|
||||
0.00180495, 0.00185301, 0.00190235, 0.00195301, 0.00200502, 0.00205841,
|
||||
0.00211322, 0.0021695, 0.00222727, 0.00228658, 0.00234747, 0.00240998,
|
||||
0.00247416, 0.00254004, 0.00260768, 0.00267712, 0.00274841, 0.0028216,
|
||||
0.00289674, 0.00297387, 0.00305306, 0.00313436, 0.00321783, 0.00330352,
|
||||
0.00339149, 0.0034818, 0.00357452, 0.0036697, 0.00376742, 0.00386775, 0.00397074,
|
||||
0.00407648, 0.00418503, 0.00429648, 0.00441089, 0.00452835, 0.00464893,
|
||||
0.00477273, 0.00489982, 0.0050303, 0.00516425, 0.00530177, 0.00544295,
|
||||
0.00558789, 0.00573669, 0.00588946, 0.00604629, 0.0062073, 0.00637259,
|
||||
0.00654229, 0.0067165, 0.00689536, 0.00707898, 0.00726748, 0.00746101,
|
||||
0.00765969, 0.00786366, 0.00807306, 0.00828804, 0.00850874, 0.00873532,
|
||||
0.00896794, 0.00920675, 0.00945191, 0.00970361, 0.00996201, 0.0102273,
|
||||
0.0104996, 0.0107792, 0.0110663, 0.0113609, 0.0116635, 0.0119741, 0.0122929,
|
||||
0.0126203, 0.0129564, 0.0133014, 0.0136556, 0.0140192, 0.0143925, 0.0147758,
|
||||
0.0151692, 0.0155732, 0.0159879, 0.0164136, 0.0168507, 0.0172994, 0.0177601,
|
||||
0.018233, 0.0187186, 0.019217, 0.0197288, 0.0202541, 0.0207935, 0.0213472,
|
||||
0.0219156, 0.0224992, 0.0230984, 0.0237135, 0.0243449, 0.0249932, 0.0256588,
|
||||
0.026342, 0.0270435, 0.0277636, 0.028503, 0.029262, 0.0300412, 0.0308412,
|
||||
0.0316624, 0.0325056, 0.0333712, 0.0342598, 0.0351721, 0.0361087, 0.0370703,
|
||||
0.0380574, 0.0390709, 0.0401113, 0.0411794, 0.042276, 0.0434017, 0.0445575,
|
||||
0.045744, 0.0469622, 0.0482127, 0.0494966, 0.0508146, 0.0521678, 0.053557,
|
||||
0.0549831, 0.0564473, 0.0579504, 0.0594936, 0.0610779, 0.0627043, 0.0643741,
|
||||
0.0660883, 0.0678482, 0.0696549, 0.0715097, 0.073414, 0.0753689, 0.0773759,
|
||||
0.0794364, 0.0815517, 0.0837234, 0.0859528, 0.0882417, 0.0905915, 0.0930039,
|
||||
0.0954805, 0.098023, 0.100633, 0.103313, 0.106064, 0.108889, 0.111788, 0.114765,
|
||||
0.117821, 0.120959, 0.12418, 0.127486, 0.130881, 0.134366, 0.137945, 0.141618,
|
||||
0.145389, 0.149261, 0.153235, 0.157316, 0.161505, 0.165806, 0.170221, 0.174754,
|
||||
0.179407, 0.184185, 0.18909, 0.194125, 0.199294, 0.204601, 0.21005, 0.215643,
|
||||
0.221385, 0.227281, 0.233333, 0.239546, 0.245925, 0.252474, 0.259197, 0.266099,
|
||||
0.273185, 0.28046, 0.287929, 0.295596, 0.303467, 0.311549, 0.319845, 0.328362,
|
||||
0.337106, 0.346083, 0.355299, 0.36476, 0.374473, 0.384445, 0.394682, 0.405192,
|
||||
0.415982, 0.42706, 0.438432, 0.450107, 0.462093, 0.474398, 0.487031
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
//
|
||||
// Energy Loss Fuction (ELF) for water
|
||||
|
||||
const G4double G4LowPAIH2O::theELFsum[1007] = {
|
||||
|
||||
0.343701, 0.338322, 0.331699, 0.32522, 0.32051, 0.313544, 0.304649, 0.297559,
|
||||
0.289704, 0.282644, 0.274489, 0.264361, 0.255236, 0.245748, 0.236871, 0.228919,
|
||||
0.221906, 0.214845, 0.206271, 0.198028, 0.190106, 0.182071, 0.173805, 0.166123,
|
||||
0.159188, 0.151848, 0.14468, 0.138038, 0.132675, 0.127068, 0.121363, 0.116174,
|
||||
0.110695, 0.10539, 0.100535, 0.0958877, 0.0916441, 0.0878014, 0.0841337,
|
||||
0.0806099, 0.0774056, 0.0731865, 0.0718562, 0.0685493, 0.065072, 0.0645778,
|
||||
0.0627131, 0.0611187, 0.0595864, 0.0582351, 0.0570597, 0.0556476, 0.0545836,
|
||||
0.0535382, 0.0526438, 0.051649, 0.0505599, 0.0496273, 0.0489336, 0.0479354,
|
||||
0.0472902, 0.0466596, 0.0457391, 0.0451427, 0.0444471, 0.0437851, 0.0432295,
|
||||
0.0426777, 0.0419665, 0.0414367, 0.0408504, 0.0403443, 0.0397835, 0.0392967,
|
||||
0.0389018, 0.0383693, 0.0378514, 0.0374829, 0.0369796, 0.0367081, 0.0362265,
|
||||
0.0358779, 0.0355725, 0.035119, 0.0348648, 0.0344976, 0.0341371, 0.0338999,
|
||||
0.0335476, 0.0332797, 0.0330546, 0.0327189, 0.0323864, 0.032056, 0.0318024,
|
||||
0.0316622, 0.0313428, 0.031206, 0.0309285, 0.0307598, 0.0305957, 0.0303611,
|
||||
0.0301941, 0.0301014, 0.0298693, 0.0297723, 0.0296079, 0.0294363, 0.029396,
|
||||
0.0294251, 0.0293818, 0.0294662, 0.0296168, 0.0297788, 0.0301786, 0.0307169,
|
||||
0.0315479, 0.0327722, 0.0342432, 0.036205, 0.0384716, 0.0420536, 0.0476498,
|
||||
0.0574523, 0.0721343, 0.106124, 0.117998, 0.120116, 0.109687, 0.0915872,
|
||||
0.066625, 0.0458, 0.0343237, 0.0254945, 0.0204653, 0.0164614, 0.0138845,
|
||||
0.0121716, 0.0110882, 0.0102305, 0.0153323, 0.00922561, 0.00907538, 0.00912068,
|
||||
0.0092554, 0.00966081, 0.0100684, 0.0106331, 0.0111436, 0.0117403, 0.0122232,
|
||||
0.0128286, 0.0133119, 0.013764, 0.0139136, 0.0137185, 0.0130353, 0.012035,
|
||||
0.0109236, 0.0100244, 0.00902829, 0.00812679, 0.00734715, 0.00657945, 0.00593111,
|
||||
0.00533323, 0.0047942, 0.00429417, 0.00387625, 0.00348138, 0.0031574, 0.00290842,
|
||||
0.00278184, 0.00275416, 0.00287829, 0.00334779, 0.00401539, 0.00521023,
|
||||
0.00708225, 0.0097644, 0.0140521, 0.0183347, 0.0250544, 0.0399675, 0.0587405,
|
||||
0.0840311, 0.121028, 0.160966, 0.203027, 0.211079, 0.217312, 0.227821, 0.235095,
|
||||
0.24169, 0.252298, 0.258592, 0.262752, 0.265536, 0.276661, 0.275552, 0.274533,
|
||||
0.269661, 0.270219, 0.265797, 0.257128, 0.245891, 0.23504, 0.223146, 0.208363,
|
||||
0.193196, 0.17773, 0.164163, 0.153071, 0.141107, 0.126677, 0.113678, 0.101827,
|
||||
0.0886036, 0.0743801, 0.0618476, 0.0499254, 0.0367243, 0.0261855, 0.0232968,
|
||||
0.0202302, 0.0176638, 0.0151418, 0.0124048, 0.0100069, 0.00849212, 0.00721195,
|
||||
0.00611224, 0.00488681, 0.00485658, 0.00444412, 0.00363214, 0.00325423,
|
||||
0.00293729, 0.0027827, 0.00264948, 0.00258351, 0.00253143, 0.00246953,
|
||||
0.00243187, 0.00237879, 0.00223043, 0.00214095, 0.00207511, 0.00203558,
|
||||
0.00199335, 0.00192966, 0.00183032, 0.00172071, 0.00158785, 0.00147243,
|
||||
0.0013439, 0.00124105, 0.00114029, 0.001058, 0.000975114, 0.000892649,
|
||||
0.000830566, 0.000773989, 0.000723575, 0.000665725, 0.000616754, 0.000579494,
|
||||
0.000523586, 0.00049199, 0.000472557, 0.000449239, 0.000431062, 0.000409861,
|
||||
0.000388832, 0.000370606, 0.000354888, 0.000338291, 0.000326973, 0.000321925,
|
||||
0.000319208, 0.000317914, 0.000318873, 0.000322065, 0.000328313, 0.000335467,
|
||||
0.000345962, 0.000356796, 0.000369682, 0.000388372, 0.000408962, 0.00043066,
|
||||
0.000452471, 0.000489845, 0.000529109, 0.000572854, 0.000621666, 0.000680914,
|
||||
0.000740288, 0.000816467, 0.000908885, 0.00100946, 0.00114474, 0.00128348,
|
||||
0.00141561, 0.00156923, 0.00168858, 0.00174342, 0.00175514, 0.00166801,
|
||||
0.0015318, 0.00105924, 0.000840322, 0.000657855, 0.000473997, 0.00029131,
|
||||
0.000168926, 0.000140695, 0.000128445, 0.000124845, 0.000123977, 0.000122763,
|
||||
0.00012008, 0.00010938, 0.000100936, 9.46588e-05, 8.99595e-05, 8.5502e-05,
|
||||
7.99431e-05, 7.54954e-05, 7.22003e-05, 6.93847e-05, 6.79397e-05, 6.70749e-05,
|
||||
6.62253e-05, 6.61113e-05, 6.77887e-05, 7.05426e-05, 7.2218e-05, 7.40878e-05,
|
||||
7.84424e-05, 8.32266e-05, 8.84459e-05, 9.52342e-05, 0.00010135, 0.000110116,
|
||||
0.000119698, 0.000127913, 0.000142122, 0.000154316, 0.000173446, 0.000199033,
|
||||
0.000235344, 0.000266991, 0.000299439, 0.00031852, 0.000321345, 0.000320485,
|
||||
0.00031236, 0.000282171, 0.000224058, 0.000134947, 9.34181e-05, 6.87239e-05,
|
||||
5.10966e-05, 3.96443e-05, 3.55887e-05, 2.50008e-05, 1.97753e-05, 1.67933e-05,
|
||||
1.43874e-05, 1.22857e-05, 1.07103e-05, 9.9882e-06, 9.55529e-06, 9.45036e-06,
|
||||
9.63188e-06, 9.96535e-06, 1.01485e-05, 1.03076e-05, 1.0405e-05, 1.04779e-05,
|
||||
1.03146e-05, 1.01275e-05, 9.76685e-06, 9.32094e-06, 8.1128e-06, 5.18542e-06,
|
||||
3.36972e-06, 2.28825e-06, 1.77385e-06, 1.48604e-06, 1.30301e-06, 1.1547e-06,
|
||||
1.09367e-06, 1.128e-06, 1.23206e-06, 1.46642e-06, 1.73534e-06, 2.03945e-06,
|
||||
2.32915e-06, 2.59852e-06, 2.71171e-06, 2.81681e-06, 2.88823e-06, 2.95867e-06,
|
||||
3.01136e-06, 3.02957e-06, 2.99639e-06, 2.90383e-06, 2.75796e-06, 2.53457e-06,
|
||||
2.20994e-06, 1.87411e-06, 1.52972e-06, 1.18165e-06, 9.14966e-07, 7.1684e-07,
|
||||
5.77823e-07, 4.91715e-07, 4.44251e-07, 4.19278e-07, 3.98474e-07, 3.79573e-07,
|
||||
3.6493e-07, 3.49207e-07, 3.36684e-07, 3.22787e-07, 3.05344e-07, 2.88179e-07,
|
||||
2.71379e-07, 2.52029e-07, 2.31401e-07, 2.11463e-07, 1.92818e-07, 1.75395e-07,
|
||||
1.56274e-07, 1.39251e-07, 1.24357e-07, 1.14166e-07, 1.09005e-07, 1.07229e-07,
|
||||
1.07939e-07, 1.09923e-07, 1.14802e-07, 1.20729e-07, 1.2667e-07, 1.30778e-07,
|
||||
1.34412e-07, 1.353e-07, 1.35255e-07, 1.33352e-07, 1.30877e-07, 1.24656e-07,
|
||||
1.1523e-07, 9.82685e-08, 7.80301e-08, 6.22455e-08, 5.11626e-08, 4.26378e-08,
|
||||
3.49651e-08, 2.85412e-08, 2.52526e-08, 2.26017e-08, 2.10365e-08, 2.03456e-08,
|
||||
1.85169e-08, 1.784e-08, 1.72669e-08, 1.64828e-08, 1.50933e-08, 1.42117e-08,
|
||||
1.36272e-08, 1.3309e-08, 1.31507e-08, 1.34033e-08, 1.24588e-08, 1.1836e-08,
|
||||
1.1246e-08, 1.04646e-08, 9.5612e-09, 8.13265e-09, 6.5166e-09, 5.36704e-09,
|
||||
4.39996e-09, 3.7338e-09, 3.23547e-09, 2.88829e-09, 2.63234e-09, 2.41013e-09,
|
||||
2.23222e-09, 2.04846e-09, 1.90159e-09, 1.75712e-09, 1.57936e-09, 1.46947e-09,
|
||||
1.37036e-09, 1.31071e-09, 1.21947e-09, 1.05641e-09, 8.98271e-10, 7.69237e-10,
|
||||
6.52693e-10, 6.09908e-10, 5.94159e-10, 5.8809e-10, 5.80861e-10, 6.03393e-10,
|
||||
6.19614e-10, 6.27668e-10, 6.43036e-10, 6.66392e-10, 7.14854e-10, 7.68705e-10,
|
||||
8.35919e-10, 8.92526e-10, 9.57347e-10, 1.02921e-09, 1.09379e-09, 1.1597e-09,
|
||||
1.21236e-09, 1.28534e-09, 1.35021e-09, 1.42768e-09, 1.48883e-09, 1.56739e-09,
|
||||
1.63815e-09, 1.70417e-09, 1.78093e-09, 1.85677e-09, 1.93572e-09, 2.01793e-09,
|
||||
2.1132e-09, 2.19675e-09, 2.28431e-09, 2.35885e-09, 2.42877e-09, 2.50647e-09,
|
||||
2.60432e-09, 2.76878e-09, 2.97722e-09, 3.21569e-09, 3.40185e-09, 3.68834e-09,
|
||||
4.14105e-09, 4.40767e-09, 4.77438e-09, 5.17213e-09, 5.58864e-09, 5.96795e-09,
|
||||
6.38569e-09, 6.85652e-09, 7.24103e-09, 7.60813e-09, 7.70074e-09, 7.84358e-09,
|
||||
8.16024e-09, 8.84067e-09, 1.37338e-08, 2.60346e-08, 4.4736e-08, 7.19727e-08,
|
||||
1.18248e-07, 2.25675e-07, 7.52606e-07, 3.45946e-05, 0.000184565, 0.000635798,
|
||||
0.00103903, 0.0019317, 0.0182683, 0.0322752, 0.0456558, 0.0590582, 0.0728399,
|
||||
0.0887233, 0.105449, 0.120398, 0.137241, 0.147511, 0.150233, 0.144037, 0.133044,
|
||||
0.119254, 0.102717, 0.0833649, 0.0724089, 0.073295, 0.085751, 0.105138, 0.125623,
|
||||
0.143651, 0.15568, 0.163681, 0.170532, 0.176964, 0.183206, 0.190715, 0.199072,
|
||||
0.206747, 0.214796, 0.224665, 0.235198, 0.247949, 0.261726, 0.278921, 0.299982,
|
||||
0.324028, 0.349266, 0.377322, 0.406436, 0.438649, 0.470931, 0.498468, 0.524826,
|
||||
0.548057, 0.567545, 0.58861, 0.623154, 0.745122, 0.731576, 0.795212, 0.864073,
|
||||
0.916613, 0.925369, 0.899703, 0.244356, 0.252615, 0.261018, 0.269569, 0.27827,
|
||||
0.28712, 0.296119, 0.305263, 0.31455, 0.323972, 0.333522, 0.343189, 0.35296,
|
||||
0.362819, 0.372747, 0.382722, 0.392719, 0.402707, 0.412654, 0.422523, 0.43227,
|
||||
0.44185, 0.451211, 0.460298, 0.46905, 0.477403, 0.48529, 0.492639, 0.499376,
|
||||
0.504367, 0.509777, 0.514929, 0.518523, 0.521151, 0.522737, 0.523212, 0.522524,
|
||||
0.520632, 0.517512, 0.513156, 0.507572, 0.500784, 0.492833, 0.483774, 0.473678,
|
||||
0.462625, 0.450709, 0.438027, 0.424686, 0.410794, 0.39646, 0.381793, 0.366898,
|
||||
0.351875, 0.336819, 0.321818, 0.306951, 0.292288, 0.272404, 0.258131, 0.244245,
|
||||
0.230786, 0.217783, 0.205262, 0.193237, 0.18172, 0.170717, 0.160228, 0.15025,
|
||||
0.140775, 0.131796, 0.123299, 0.11527, 0.107696, 0.100558, 0.0938403, 0.0875248,
|
||||
0.0815935, 0.0760284, 0.0708116, 0.0659252, 0.0613519, 0.0570747, 0.0530771,
|
||||
0.0493433, 0.0458578, 0.0426059, 0.0395735, 0.0367473, 0.0341144, 0.0316626,
|
||||
0.0293804, 0.0272569, 0.0252818, 0.0234452, 0.0217382, 0.0201519, 0.0186783,
|
||||
0.0173098, 0.0160392, 0.0148597, 0.0137651, 0.0127495, 0.0118075, 0.0109337,
|
||||
0.0101236, 0.00937242, 0.00867615, 0.00803086, 0.00743288, 0.00687884,
|
||||
0.00636558, 0.00589016, 0.00544984, 0.00504208, 0.00466452, 0.00431495,
|
||||
0.00399133, 0.00369177, 0.0034145, 0.00315789, 0.00292042, 0.00336515,
|
||||
0.00310903, 0.00287178, 0.0026521, 0.00244876, 0.00226062, 0.00208661,
|
||||
0.00192571, 0.00177698, 0.00163954, 0.00151256, 0.00139527, 0.00128696,
|
||||
0.00118696, 0.00109464, 0.00100944, 0.000930809, 0.000858257, 0.000791323,
|
||||
0.000729578, 0.000672625, 0.000620099, 0.000571659, 0.000526992, 0.000485805,
|
||||
0.000447831, 0.000412821, 0.000380545, 0.000350791, 0.000323363, 0.000298079,
|
||||
0.000274774, 0.000253293, 0.000233492, 0.000215242, 0.000198421, 0.000182917,
|
||||
0.000168626, 0.000155455, 0.000143316, 0.000132126, 0.000121813, 0.000112308,
|
||||
0.000103546, 9.547e-05, 8.8026e-05, 8.11643e-05, 7.48394e-05, 6.90091e-05,
|
||||
6.36347e-05, 5.86803e-05, 5.4113e-05, 4.99025e-05, 4.60209e-05, 4.24422e-05,
|
||||
3.91429e-05, 3.6101e-05, 3.32964e-05, 3.07105e-05, 2.83261e-05, 2.61275e-05,
|
||||
2.41002e-05, 2.22307e-05, 2.05068e-05, 1.8917e-05, 1.74509e-05, 1.60987e-05,
|
||||
1.48518e-05, 1.37016e-05, 1.26409e-05, 1.16625e-05, 1.07601e-05, 9.92771e-06,
|
||||
9.1599e-06, 8.45163e-06, 7.79829e-06, 7.19558e-06, 6.63956e-06, 6.12673e-06,
|
||||
5.65369e-06, 5.21733e-06, 4.81479e-06, 4.44345e-06, 4.10087e-06, 3.78481e-06,
|
||||
3.49321e-06, 3.22417e-06, 2.97593e-06, 2.74688e-06, 2.53553e-06, 2.34051e-06,
|
||||
2.16054e-06, 1.99446e-06, 1.8412e-06, 1.69976e-06, 1.56922e-06, 1.44874e-06,
|
||||
1.33754e-06, 1.23491e-06, 1.14018e-06, 1.05274e-06, 9.72031e-07, 8.97527e-07,
|
||||
8.28751e-07, 7.65262e-07, 7.06652e-07, 6.52544e-07, 6.02591e-07, 5.56473e-07,
|
||||
5.13895e-07, 4.74583e-07, 4.38287e-07, 4.04775e-07, 3.73831e-07, 3.45259e-07,
|
||||
3.18877e-07, 2.94515e-07, 2.7202e-07, 2.51246e-07, 2.32063e-07, 2.14348e-07,
|
||||
1.97988e-07, 1.8288e-07, 1.68927e-07, 1.56041e-07, 1.4414e-07, 1.33148e-07,
|
||||
1.22997e-07, 1.13621e-07, 1.04961e-07, 9.69623e-08, 8.95744e-08, 8.27505e-08,
|
||||
7.64473e-08, 7.06252e-08, 6.52472e-08, 6.02795e-08, 5.56907e-08, 5.14518e-08,
|
||||
4.75361e-08, 4.39188e-08, 4.05772e-08, 3.74902e-08, 3.46383e-08, 3.20037e-08,
|
||||
2.95698e-08, 2.73212e-08, 2.52438e-08, 2.33245e-08, 2.15513e-08, 1.99131e-08,
|
||||
1.83995e-08, 1.70011e-08, 1.5709e-08, 1.45153e-08, 1.34123e-08, 1.23933e-08,
|
||||
1.14517e-08, 1.05817e-08, 9.77786e-09, 9.03513e-09, 8.34886e-09, 7.71475e-09,
|
||||
7.12884e-09, 6.58746e-09, 6.08722e-09, 5.62498e-09, 5.19787e-09, 4.80321e-09,
|
||||
4.43853e-09, 4.10156e-09, 3.79018e-09, 3.50245e-09, 3.23657e-09, 2.99089e-09,
|
||||
2.76387e-09, 2.55408e-09, 2.36023e-09, 2.18109e-09, 2.01556e-09, 1.8626e-09,
|
||||
1.72125e-09, 1.59062e-09, 1.46992e-09, 1.35838e-09, 1.2553e-09, 1.16005e-09,
|
||||
1.07203e-09, 9.90691e-10, 9.15525e-10, 8.46063e-10, 7.81873e-10, 7.22554e-10,
|
||||
6.67737e-10, 6.1708e-10, 5.70266e-10, 5.27005e-10, 4.87027e-10, 4.50082e-10,
|
||||
4.15937e-10, 3.84386e-10, 3.55229e-10, 3.28284e-10, 3.03384e-10, 2.80373e-10,
|
||||
2.59107e-10, 2.39455e-10, 2.21293e-10, 2.04509e-10, 1.88999e-10, 1.74665e-10,
|
||||
1.61418e-10, 1.49176e-10, 1.37863e-10, 1.27408e-10, 1.17745e-10, 1.08816e-10,
|
||||
1.00564e-10, 9.29376e-11, 8.58897e-11, 7.93764e-11, 7.33571e-11, 6.77943e-11,
|
||||
6.26534e-11, 5.79023e-11, 5.35116e-11, 4.94538e-11, 4.57038e-11, 4.22381e-11,
|
||||
3.90353e-11, 3.60753e-11, 3.33399e-11, 3.08118e-11, 2.84755e-11, 2.63163e-11,
|
||||
2.43209e-11, 2.24767e-11, 2.07724e-11, 1.91974e-11, 1.77418e-11, 1.63965e-11,
|
||||
1.51533e-11, 1.40043e-11, 1.29425e-11, 1.19612e-11, 1.10542e-11, 1.02161e-11,
|
||||
9.44151e-12, 8.72564e-12, 8.06406e-12, 7.45264e-12, 6.88758e-12, 6.36536e-12,
|
||||
5.88274e-12, 5.43672e-12, 5.02451e-12, 4.64356e-12, 4.29149e-12, 3.96612e-12,
|
||||
3.66541e-12
|
||||
|
||||
};
|
||||
|
||||
//////////////////////////////
|
||||
//
|
||||
// Rutherford term (\int of ELF*omega) of the PAI model for water
|
||||
|
||||
const G4double G4LowPAIH2O::theRuthSum[1007] = {
|
||||
|
||||
0, 0.000783401, 0.00231191, 0.00379636, 0.00524157, 0.00594579, 0.00730817,
|
||||
0.00862143, 0.00988839, 0.0111095, 0.0116985, 0.0128262, 0.0138996, 0.0149204,
|
||||
0.0158897, 0.0168116, 0.0176908, 0.0181112, 0.0189103, 0.0196636, 0.0203729,
|
||||
0.021186, 0.0216702, 0.0222506, 0.0227922, 0.0232961, 0.0237622, 0.0241923,
|
||||
0.024591, 0.0249609, 0.0253014, 0.0256139, 0.025899, 0.0261568, 0.026389,
|
||||
0.0265973, 0.0267833, 0.026949, 0.027096, 0.0272252, 0.0273377, 0.0274322,
|
||||
0.0275132, 0.0275827, 0.0276361, 0.0277017, 0.0277353, 0.0277681, 0.0277901,
|
||||
0.0278054, 0.0278147, 0.0278197, 0.0278173, 0.0278101, 0.0277985, 0.0277827,
|
||||
0.0277521, 0.0277273, 0.027699, 0.0276512, 0.0276159, 0.0275781, 0.0275166,
|
||||
0.0274727, 0.0274261, 0.0273525, 0.0273011, 0.0272477, 0.0271642, 0.0271063,
|
||||
0.0270167, 0.0269551, 0.0268601, 0.0267951, 0.0267287, 0.026627, 0.0265231,
|
||||
0.0264526, 0.0263451, 0.0262724, 0.0261621, 0.0260875, 0.0259747, 0.0258608,
|
||||
0.0257841, 0.0256682, 0.0255515, 0.0254732, 0.025355, 0.0252364, 0.025157,
|
||||
0.0250375, 0.0249173, 0.0247964, 0.0246752, 0.0245945, 0.0244731, 0.0243519,
|
||||
0.0242309, 0.0241101, 0.0239897, 0.0238696, 0.0237499, 0.0236308, 0.0235123,
|
||||
0.0233943, 0.023277, 0.0231601, 0.0230442, 0.0229297, 0.0228169, 0.0227057,
|
||||
0.0225968, 0.0224554, 0.0223529, 0.0222551, 0.0221633, 0.0220523, 0.0219796,
|
||||
0.0219197, 0.0218604, 0.0218367, 0.0218475, 0.0219083, 0.0220998, 0.0224082,
|
||||
0.0230219, 0.0235228, 0.024142, 0.0245011, 0.0247757, 0.0248363, 0.0247485,
|
||||
0.0246141, 0.0243745, 0.0240981, 0.0237967, 0.0234813, 0.0231588, 0.0228334,
|
||||
0.0225333, 0.022234, 0.0219117, 0.0215947, 0.0212845, 0.0209824, 0.0206894,
|
||||
0.0203363, 0.0200645, 0.0198027, 0.0194883, 0.0192469, 0.0189576, 0.0187351,
|
||||
0.0184661, 0.018203, 0.0179929, 0.017726, 0.0174531, 0.017175, 0.0168925,
|
||||
0.0166056, 0.0163156, 0.0160235, 0.0157299, 0.015436, 0.0151422, 0.0147915,
|
||||
0.0145013, 0.014213, 0.0138709, 0.0135342, 0.0132585, 0.0129349, 0.0126208,
|
||||
0.0123193, 0.0120337, 0.0117686, 0.0115317, 0.0113322, 0.0111617, 0.0110782,
|
||||
0.0110721, 0.0112368, 0.0116636, 0.0124264, 0.0136592, 0.0154631, 0.0178602,
|
||||
0.0186456, 0.019052, 0.0198976, 0.0203379, 0.0207921, 0.0217337, 0.0222207,
|
||||
0.0227174, 0.0232199, 0.0242497, 0.0247726, 0.0252907, 0.0257995, 0.0268004,
|
||||
0.027293, 0.0277682, 0.0282184, 0.029062, 0.0294548, 0.0298151, 0.0301393,
|
||||
0.0304269, 0.0309315, 0.0311538, 0.0313486, 0.0315121, 0.0317741, 0.0318756,
|
||||
0.0319479, 0.0319883, 0.0319978, 0.0319606, 0.0319133, 0.0318389, 0.0317495,
|
||||
0.0316536, 0.0315517, 0.0313376, 0.0312253, 0.0311076, 0.0309859, 0.0308616,
|
||||
0.0307351, 0.0306065, 0.0303482, 0.0302194, 0.0300899, 0.0299595, 0.029829,
|
||||
0.0296985, 0.0294387, 0.0293095, 0.0291807, 0.0290523, 0.0289245, 0.0287971,
|
||||
0.0285437, 0.028292, 0.0280423, 0.0277946, 0.0276715, 0.0274268, 0.027184,
|
||||
0.0269429, 0.0268229, 0.026584, 0.0263467, 0.0261111, 0.0259939, 0.0257606,
|
||||
0.0255291, 0.0252993, 0.0250713, 0.024958, 0.0247326, 0.024509, 0.0242873,
|
||||
0.0240673, 0.0238492, 0.0236329, 0.0235254, 0.0233118, 0.0231001, 0.0228903,
|
||||
0.0226823, 0.022476, 0.0222716, 0.022069, 0.022063, 0.0216692, 0.021472,
|
||||
0.0212766, 0.021083, 0.0208912, 0.0207011, 0.0205129, 0.0203264, 0.0201416,
|
||||
0.0199586, 0.0197774, 0.0195979, 0.0194202, 0.0192441, 0.0190699, 0.0188974,
|
||||
0.0187266, 0.0185577, 0.0183905, 0.0181431, 0.0179803, 0.0178194, 0.0176605,
|
||||
0.0175035, 0.0173486, 0.0171198, 0.0169697, 0.0168216, 0.0166752, 0.0165303,
|
||||
0.0163153, 0.016173, 0.0160307, 0.0158173, 0.0156757, 0.0155346, 0.0153939,
|
||||
0.0151843, 0.0150458, 0.0148403, 0.0147048, 0.0145705, 0.0143715, 0.0142403,
|
||||
0.0140457, 0.0139174, 0.0137902, 0.0136017, 0.0134774, 0.013293, 0.0131715,
|
||||
0.0129913, 0.0128135, 0.0126964, 0.0125226, 0.0124081, 0.0122383, 0.0120709,
|
||||
0.0119605, 0.0117969, 0.0116891, 0.0115292, 0.0113716, 0.0112162, 0.0111138,
|
||||
0.0109619, 0.0108123, 0.0106647, 0.0105675, 0.0104234, 0.0102814, 0.0101415,
|
||||
0.0100036, 0.00986787, 0.00973419, 0.00960257, 0.00947294, 0.00934516,
|
||||
0.00921914, 0.00909482, 0.00897207, 0.00885071, 0.0087305, 0.0086115, 0.0084939,
|
||||
0.00837777, 0.00826314, 0.00811266, 0.00800156, 0.00789193, 0.00778377,
|
||||
0.00764184, 0.00753708, 0.00743375, 0.00729816, 0.0071981, 0.0070668, 0.00696991,
|
||||
0.00684278, 0.00674896, 0.00662588, 0.00653504, 0.00641585, 0.0063279,
|
||||
0.00621249, 0.00609919, 0.00598796, 0.00590586, 0.00579813, 0.00569234,
|
||||
0.00558847, 0.00548648, 0.00538636, 0.00528806, 0.00519155, 0.00509681,
|
||||
0.00500379, 0.00491247, 0.00482282, 0.00473481, 0.00464841, 0.00454262,
|
||||
0.00445973, 0.00441886, 0.00437835, 0.0043183, 0.00427872, 0.00423951,
|
||||
0.00420066, 0.00416216, 0.00410507, 0.00406745, 0.00403017, 0.00397489,
|
||||
0.00393846, 0.00390236, 0.00384883, 0.00381354, 0.00377859, 0.00372675,
|
||||
0.00369258, 0.00365873, 0.00360853, 0.00357545, 0.0035264, 0.00349407,
|
||||
0.00344613, 0.00341454, 0.00338323, 0.00333682, 0.00329104, 0.00326086,
|
||||
0.00321613, 0.00318664, 0.00314292, 0.00311411, 0.00307138, 0.00302924,
|
||||
0.00300172, 0.00296029, 0.00291967, 0.00289291, 0.00285321, 0.00281407,
|
||||
0.00278827, 0.00275001, 0.00271228, 0.00267507, 0.00263837, 0.00261418,
|
||||
0.00257831, 0.00254294, 0.00250805, 0.00247364, 0.0024397, 0.00240622,
|
||||
0.00237321, 0.00234065, 0.00230854, 0.00227686, 0.00224562, 0.00221481,
|
||||
0.00218442, 0.00215445, 0.00212489, 0.00209574, 0.00206698, 0.00202926,
|
||||
0.00200141, 0.00197395, 0.00194687, 0.00191134, 0.00188511, 0.00185925,
|
||||
0.00182531, 0.00180027, 0.00176741, 0.00174316, 0.00171134, 0.00168786,
|
||||
0.00165706, 0.00163432, 0.00160449, 0.00158248, 0.00155359, 0.00152524,
|
||||
0.0014974, 0.00147685, 0.00144998, 0.00142343, 0.00139745, 0.00137195,
|
||||
0.00134691, 0.00132232, 0.00129819, 0.00127449, 0.00125123, 0.00122839,
|
||||
0.00120597, 0.00118396, 0.00116235, 0.00113589, 0.00111516, 0.00109481,
|
||||
0.00106989, 0.00105036, 0.00102645, 0.00100771, 0.000984776, 0.00096236,
|
||||
0.000944795, 0.000923289, 0.000902272, 0.000881734, 0.000861663, 0.000842049,
|
||||
0.000822882, 0.000804151, 0.000785846, 0.000767958, 0.000750477, 0.000730025,
|
||||
0.000713407, 0.000697168, 0.000678168, 0.000659686, 0.00064467, 0.000627101,
|
||||
0.000610011, 0.000593386, 0.000577215, 0.000561484, 0.000546182, 0.000531297,
|
||||
0.000514444, 0.000500424, 0.000486786, 0.000471344, 0.000456392, 0.000441914,
|
||||
0.000427896, 0.000414322, 0.000401179, 0.000388453, 0.000374402, 0.000362525,
|
||||
0.000349412, 0.000336774, 0.000324593, 0.000312852, 0.000301536, 0.000290629,
|
||||
0.00027883, 0.00026751, 0.000256649, 0.000246235, 0.000236233, 0.000225601,
|
||||
0.000215447, 0.000205751, 0.000196491, 0.000187648, 0.000178381, 0.000169572,
|
||||
0.0001612, 0.000152547, 0.000144823, 0.000139991, 0.000140589, 0.000146924,
|
||||
0.000163174, 0.00027459, 0.000556121, 0.000987089, 0.00156066, 0.00241699,
|
||||
0.00328156, 0.00451532, 0.00569793, 0.00729826, 0.0090396, 0.0108219, 0.0125318,
|
||||
0.0140779, 0.015413, 0.016505, 0.0173227, 0.0179117, 0.0184991, 0.0190787,
|
||||
0.0199878, 0.0211842, 0.0226481, 0.0243037, 0.0260656, 0.0278894, 0.0297607,
|
||||
0.0319413, 0.0338936, 0.0361926, 0.0385534, 0.040971, 0.0434633, 0.0460499,
|
||||
0.0487535, 0.0519478, 0.0553268, 0.0589571, 0.0628979, 0.067179, 0.0723321,
|
||||
0.0778967, 0.0839009, 0.0903606, 0.0972024, 0.105039, 0.113101, 0.121291,
|
||||
0.130311, 0.139594, 0.149138, 0.162421, 0.175168, 0.190137, 0.206066, 0.221952,
|
||||
0.237589, 0.239452, 0.233554, 0.22817, 0.223279, 0.21886, 0.214892, 0.211355,
|
||||
0.208231, 0.205504, 0.203155, 0.20117, 0.199533, 0.198228, 0.197241, 0.196558,
|
||||
0.196165, 0.196047, 0.196192, 0.196584, 0.19721, 0.198054, 0.199103, 0.200341,
|
||||
0.201752, 0.203318, 0.205023, 0.206849, 0.208777, 0.210786, 0.212842, 0.214926,
|
||||
0.217038, 0.219155, 0.221242, 0.223276, 0.225233, 0.227086, 0.228812, 0.230385,
|
||||
0.231782, 0.23298, 0.233958, 0.234697, 0.235181, 0.235394, 0.235326, 0.234967,
|
||||
0.234312, 0.233357, 0.232103, 0.230551, 0.228707, 0.22658, 0.224178, 0.221515,
|
||||
0.218602, 0.215457, 0.212095, 0.208462, 0.204579, 0.200534, 0.196346, 0.192033,
|
||||
0.187615, 0.183109, 0.178532, 0.173902, 0.169233, 0.164542, 0.159841, 0.155145,
|
||||
0.150466, 0.145815, 0.141203, 0.136638, 0.13213, 0.127686, 0.123312, 0.119015,
|
||||
0.114801, 0.110672, 0.106635, 0.10269, 0.098842, 0.0950917, 0.0914411, 0.0878912,
|
||||
0.0844426, 0.0810957, 0.0778502, 0.0747058, 0.0716619, 0.0687174, 0.0658712,
|
||||
0.063122, 0.0604682, 0.0579081, 0.05544, 0.0530619, 0.0507717, 0.0485675,
|
||||
0.046447, 0.0444081, 0.0424485, 0.040566, 0.0387584, 0.0370233, 0.0353586,
|
||||
0.0337619, 0.0322311, 0.0307639, 0.0293582, 0.0280118, 0.0267226, 0.0254886,
|
||||
0.0243077, 0.023178, 0.0220975, 0.0210643, 0.0200767, 0.0191328, 0.0182309,
|
||||
0.0173779, 0.016571, 0.015799, 0.0150607, 0.0143549, 0.0136801, 0.0130353,
|
||||
0.0124192, 0.0118306, 0.0112686, 0.0107319, 0.0102196, 0.00973068, 0.00926409,
|
||||
0.00881894, 0.0083943, 0.00798931, 0.00760313, 0.00723493, 0.00688394, 0.0065494,
|
||||
0.00623059, 0.00592681, 0.00563739, 0.0053617, 0.00509911, 0.00484903,
|
||||
0.00461089, 0.00438416, 0.0041683, 0.00396282, 0.00376724, 0.0035811, 0.00340396,
|
||||
0.00323541, 0.00307504, 0.00292246, 0.00277732, 0.00263926, 0.00250794,
|
||||
0.00238305, 0.00226428, 0.00215134, 0.00204394, 0.00194183, 0.00184475,
|
||||
0.00175246, 0.00166472, 0.00158132, 0.00150205, 0.0014267, 0.00135509,
|
||||
0.00128704, 0.00122237, 0.00116091, 0.00110251, 0.00104702, 0.000994296,
|
||||
0.000944203, 0.000896612, 0.000851398, 0.000808446, 0.000767644, 0.000728884,
|
||||
0.000692067, 0.000657096, 0.000623879, 0.00059233, 0.000562366, 0.000533908,
|
||||
0.000506881, 0.000481213, 0.000456838, 0.00043369, 0.000411709, 0.000390836,
|
||||
0.000371015, 0.000352195, 0.000334325, 0.000317357, 0.000301246, 0.000285949,
|
||||
0.000271426, 0.000257637, 0.000244546, 0.000232118, 0.000220318, 0.000209116,
|
||||
0.000198482, 0.000188387, 0.000178803, 0.000169705, 0.000161069, 0.00015287,
|
||||
0.000145088, 0.000137701, 0.000130689, 0.000124033, 0.000117714, 0.000111717,
|
||||
0.000106025, 0.000100622, 9.54938e-05, 9.06262e-05, 8.60062e-05, 8.16212e-05,
|
||||
7.74592e-05, 7.35091e-05, 6.976e-05, 6.62017e-05, 6.28245e-05, 5.96193e-05,
|
||||
5.65774e-05, 5.36904e-05, 5.09504e-05, 4.835e-05, 4.58822e-05, 4.35401e-05,
|
||||
4.13173e-05, 3.92079e-05, 3.7206e-05, 3.53062e-05, 3.35033e-05, 3.17923e-05,
|
||||
3.01685e-05, 2.86276e-05, 2.71653e-05, 2.57776e-05, 2.44607e-05, 2.3211e-05,
|
||||
2.20251e-05, 2.08997e-05, 1.98318e-05, 1.88184e-05, 1.78567e-05, 1.69441e-05,
|
||||
1.60781e-05, 1.52563e-05, 1.44765e-05, 1.37365e-05, 1.30343e-05, 1.2368e-05,
|
||||
1.17357e-05, 1.11357e-05, 1.05664e-05, 1.00261e-05, 9.51346e-06, 9.02701e-06,
|
||||
8.56541e-06, 8.1274e-06, 7.71178e-06, 7.31739e-06, 6.94317e-06, 6.58807e-06,
|
||||
6.25112e-06, 5.9314e-06, 5.62801e-06, 5.34014e-06, 5.06699e-06, 4.8078e-06,
|
||||
4.56186e-06, 4.3285e-06, 4.10707e-06, 3.89696e-06, 3.69759e-06, 3.50843e-06,
|
||||
3.32893e-06, 3.15861e-06, 2.99701e-06, 2.84367e-06, 2.69817e-06, 2.56011e-06,
|
||||
2.42912e-06, 2.30482e-06, 2.18689e-06, 2.07498e-06, 1.9688e-06, 1.86806e-06,
|
||||
1.77246e-06, 1.68176e-06, 1.5957e-06, 1.51404e-06, 1.43655e-06, 1.36304e-06,
|
||||
1.29328e-06, 1.22709e-06, 1.16429e-06, 1.1047e-06, 1.04816e-06, 9.94518e-07,
|
||||
9.43617e-07, 8.95321e-07, 8.49496e-07, 8.06016e-07, 7.64762e-07, 7.25618e-07,
|
||||
6.88477e-07, 6.53238e-07, 6.19801e-07, 5.88076e-07, 5.57974e-07, 5.29413e-07,
|
||||
5.02314e-07, 4.76602e-07, 4.52205e-07, 4.29057e-07, 4.07094e-07, 3.86255e-07,
|
||||
3.66483e-07, 3.47723e-07, 3.29922e-07, 3.13033e-07, 2.97009e-07, 2.81805e-07,
|
||||
2.67378e-07, 2.53691e-07, 2.40704e-07, 2.28381e-07, 2.1669e-07, 2.05597e-07,
|
||||
1.95071e-07, 1.85085e-07, 1.7561e-07, 1.66619e-07, 1.58089e-07, 1.49996e-07,
|
||||
1.42317e-07, 1.35031e-07, 1.28118e-07, 1.21559e-07, 1.15335e-07, 1.09431e-07,
|
||||
1.03828e-07, 9.85126e-08, 9.3469e-08, 8.86837e-08, 8.41433e-08, 7.98354e-08,
|
||||
7.5748e-08, 7.18699e-08, 6.81903e-08, 6.46991e-08, 6.13866e-08, 5.82437e-08,
|
||||
5.52617e-08, 5.24324e-08, 4.97479e-08, 4.72009e-08, 4.47842e-08, 4.24913e-08,
|
||||
4.03158e-08, 3.82516e-08, 3.62932e-08, 3.4435e-08, 3.26719e-08, 3.09991e-08,
|
||||
2.9412e-08, 2.79061e-08, 2.64773e-08, 2.51216e-08
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////// end of G4LowDataH2O header file ////////////////
|
||||
@@ -0,0 +1,267 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// G4LowPAIxs.hh -- header file
|
||||
//
|
||||
// GEANT 4 class header file --- Copyright CERN 1995
|
||||
// CERB Geneva Switzerland
|
||||
//
|
||||
// for information related to this code, please, contact
|
||||
// CERN, CN Division, ASD Group
|
||||
//
|
||||
// Preparation of ionizing collision cross section according to Photo Absorption
|
||||
// Ionization (PAI) model for simulation of ionization energy losses in very thin
|
||||
// layers of water for low energy protons and electrons.
|
||||
//
|
||||
// Author: Vladimir.Grichine@cern.ch
|
||||
//
|
||||
// History:
|
||||
//
|
||||
|
||||
// 2.12.24, V. Grichine: 1st version
|
||||
|
||||
#ifndef G4LOWPAIH2O_HH
|
||||
#define G4LOWPAIH2O_HH
|
||||
|
||||
#include "G4ios.hh"
|
||||
#include "globals.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4PhysicsLogVector.hh"
|
||||
#include "G4DataVector.hh"
|
||||
#include "G4PhysicsTable.hh"
|
||||
#include "G4VEmModel.hh"
|
||||
#include "G4VEmFluctuationModel.hh"
|
||||
|
||||
class G4MaterialCutsCouple;
|
||||
class G4Material;
|
||||
class G4SandiaTable;
|
||||
class G4PhysicsLogVector;
|
||||
class G4PhysicsTable;
|
||||
class G4ParticleDefinition;
|
||||
class G4ParticleChangeForLoss;
|
||||
|
||||
class G4LowPAIH2O :
|
||||
public G4VEmModel , public G4VEmFluctuationModel
|
||||
{
|
||||
public:
|
||||
// Constructors
|
||||
|
||||
explicit G4LowPAIH2O( const G4ParticleDefinition* p = nullptr,
|
||||
const G4String& nam = "lowpaih2o");
|
||||
|
||||
~G4LowPAIH2O() override;
|
||||
|
||||
G4LowPAIH2O & operator=(const G4LowPAIH2O &right) = delete;
|
||||
G4LowPAIH2O(const G4LowPAIH2O&) = delete;
|
||||
|
||||
// methods
|
||||
|
||||
void Initialise(const G4ParticleDefinition*, const G4DataVector&) override;
|
||||
|
||||
void InitialiseLocal(const G4ParticleDefinition*,
|
||||
G4VEmModel* masterModel) override;
|
||||
|
||||
G4double CrossSectionPerVolume(const G4Material*,
|
||||
const G4ParticleDefinition*,
|
||||
G4double kineticEnergy,
|
||||
G4double cutEnergy,
|
||||
G4double maxEnergy) override;
|
||||
|
||||
G4double CrossSectionPerAtom(
|
||||
const G4ParticleDefinition*,
|
||||
G4double kineticEnergy, G4double Z,
|
||||
G4double A,
|
||||
G4double cutEnergy,
|
||||
G4double maxEnergy);
|
||||
|
||||
virtual G4double ComputeCrossSectionPerElectron(
|
||||
const G4ParticleDefinition*,
|
||||
G4double kineticEnergy,
|
||||
G4double cutEnergy,
|
||||
G4double maxEnergy);
|
||||
|
||||
void SampleSecondaries(std::vector<G4DynamicParticle*>*,
|
||||
const G4MaterialCutsCouple*,
|
||||
const G4DynamicParticle*,
|
||||
G4double tmin,
|
||||
G4double maxEnergy) override;
|
||||
|
||||
G4double SampleFluctuations(const G4MaterialCutsCouple*,
|
||||
const G4DynamicParticle*,
|
||||
const G4double tcut,
|
||||
const G4double tmax,
|
||||
const G4double length,
|
||||
const G4double meanLoss) override;
|
||||
void CorrectionsAlongStep(const G4MaterialCutsCouple*,
|
||||
const G4DynamicParticle*,
|
||||
const G4double& length,
|
||||
G4double& eloss) override;
|
||||
|
||||
|
||||
G4double Dispersion(const G4Material*, const G4DynamicParticle*,
|
||||
const G4double, const G4double, const G4double) override {return 0.;};
|
||||
|
||||
inline G4double ComputeMeanFreePath( const G4ParticleDefinition*,
|
||||
G4double kineticEnergy,
|
||||
const G4Material*,
|
||||
G4double cutEnergy = 0.0,
|
||||
G4double maxEnergy = DBL_MAX);
|
||||
void Initialize();
|
||||
void InitRuthELF();
|
||||
|
||||
void BuildPhysicsTable(const G4ParticleDefinition* pd);
|
||||
void BuildPrEnergyTable();
|
||||
void BuildElEnergyTable();
|
||||
G4double GetPrTransfer( G4double Tkin);
|
||||
G4double CorrectPrTransfer( G4double Tkin);
|
||||
G4double CorrectElTransfer( G4double Tkin);
|
||||
|
||||
G4double GetElTransfer( G4double Tkin);
|
||||
G4double GetPrMFP( G4double Tkin);
|
||||
G4double GetPrdNdx( G4double Tkin);
|
||||
G4double GetElMFP( G4double Tkin);
|
||||
G4double GetEldNdx( G4double Tkin);
|
||||
G4double PrPAId2Ndxdw( G4double omega );
|
||||
G4double ElPAId2Ndxdw( G4double omega );
|
||||
|
||||
void SetBe2( G4double be2 ){ fBe2 = be2; };
|
||||
G4double GetBe2(){ return fBe2; };
|
||||
void SetOmega( G4double ww ){ fOmega = ww; };
|
||||
G4double GetOmega(){ return fOmega;};
|
||||
void SetBias( G4double bb ){ fBias = bb; };
|
||||
G4double GetBias(){ return fBias;};
|
||||
|
||||
G4double GetElectronTmax( G4double Tkin );
|
||||
G4double GetProtonTmax( G4double Tkin );
|
||||
|
||||
inline G4double GetSumELF( G4double energy );
|
||||
inline G4double GetSumRuth( G4double energy );
|
||||
|
||||
private:
|
||||
|
||||
// Local class members
|
||||
G4int fTotBin{0};
|
||||
G4int fBinTr{0};
|
||||
G4int fBias{0};
|
||||
G4double fCof{0.0};
|
||||
G4double fBeta{0.0};
|
||||
G4double fBe2{0.0};
|
||||
G4double fTkin{0.0};
|
||||
|
||||
G4double fBmin{0.0};
|
||||
G4double fBmax{0.0};
|
||||
G4double fWmin{0.0};
|
||||
G4double fWmax{0.0};
|
||||
G4double fOmega{0.0};
|
||||
G4double fElectronDensity{0.0};
|
||||
G4double fNat{0.0};
|
||||
G4double fNel{0.0};
|
||||
G4double fMass{0.0};
|
||||
|
||||
static const G4int theBin;
|
||||
static const G4double theEsum[1007], theELFsum[1007], theRuthSum[1007];
|
||||
|
||||
G4DataVector fEsum;
|
||||
G4DataVector fELFsum, fRuthSum;
|
||||
G4DataVector fPrWmaxVector;
|
||||
|
||||
G4Material* fMat{nullptr};
|
||||
|
||||
G4PhysicsLogVector* fBetaVector{nullptr};
|
||||
G4PhysicsTable* fPrEnergyTable{nullptr};
|
||||
G4PhysicsTable* fElEnergyTable{nullptr};
|
||||
G4PhysicsLogVector* fTransferVector{nullptr};
|
||||
|
||||
G4ParticleDefinition* theElectron{nullptr};
|
||||
G4ParticleDefinition* theProton{nullptr};
|
||||
G4ParticleChangeForLoss* fParticleChange{nullptr};
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//////////////// Inline methods //////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////// fast (STL) get ELF /////////////////
|
||||
|
||||
G4double G4LowPAIH2O::GetSumELF( G4double energy )
|
||||
{
|
||||
G4double ee = energy; // /CLHEP::eV;
|
||||
G4double elf(0.), y1(0.), y2(0.), x1(0.), x2(0.), aa(0.);
|
||||
|
||||
std::size_t nlow = std::lower_bound( fEsum.begin(), fEsum.end(), ee ) - fEsum.begin();
|
||||
|
||||
x1 = fEsum[nlow-1];
|
||||
x2 = fEsum[nlow];
|
||||
y1 = fELFsum[nlow-1];
|
||||
y2 = fELFsum[nlow];
|
||||
aa = (y2-y1)/(x2-x1);
|
||||
elf = y1 + aa*(ee-x1);
|
||||
return elf;
|
||||
}
|
||||
|
||||
/////////////////////// fast (STL) get Rutherford /////////////////////
|
||||
|
||||
G4double G4LowPAIH2O::GetSumRuth( G4double energy )
|
||||
{
|
||||
G4double ee = energy; // /CLHEP::eV;
|
||||
G4double ruth(0.), y1(0.), y2(0.), x1(0.), x2(0.), aa(0.);
|
||||
|
||||
std::size_t nlow = std::lower_bound( fEsum.begin(), fEsum.end(), ee ) - fEsum.begin();
|
||||
|
||||
x1 = fEsum[nlow-1];
|
||||
x2 = fEsum[nlow];
|
||||
y1 = fRuthSum[nlow-1];
|
||||
y2 = fRuthSum[nlow];
|
||||
aa = (y2-y1)/(x2-x1);
|
||||
ruth = y1 + aa*(ee-x1);
|
||||
|
||||
return ruth;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////
|
||||
|
||||
G4double G4LowPAIH2O::ComputeMeanFreePath( const G4ParticleDefinition* pd,
|
||||
G4double Tkin,
|
||||
const G4Material*,
|
||||
G4double, // cutEnergy, // = 0.0,
|
||||
G4double ) //maxEnergy ) // = DBL_MAX)
|
||||
{
|
||||
G4double dndx(0.), mfp(DBL_MAX);
|
||||
|
||||
if ( pd == theProton ) dndx = GetPrdNdx(Tkin);
|
||||
else if( pd == theElectron ) dndx = GetEldNdx(Tkin);
|
||||
else return DBL_MAX;
|
||||
|
||||
if( dndx > 0.) mfp = 1./dndx;
|
||||
else mfp = DBL_MAX;
|
||||
|
||||
mfp *= fBias;
|
||||
return mfp;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
///////////////// end of G4LowPAIH2O header file //////////////////
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user