Files
2025-06-26 09:17:29 +02:00

251 lines
9.3 KiB
C++

//
// ********************************************************************
// * 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