47G4DNAIndependentReactionTimeStepper::Utils::Utils(
const G4Track& trackA,
const G4Track& trackB)
48 : fpTrackA(const_cast<
G4Track*>(&trackA)), fpTrackB(const_cast<
G4Track*>(&trackB))
52 fUserMinTimeStep = 1 * CLHEP::ps;
57 fReactionSet->SortByTime();
64 fReactionSet->CleanAllReaction();
65 fIsInitialized =
false;
66 fSampledPositions.clear();
68 InitializeForNewTrack();
72void G4DNAIndependentReactionTimeStepper::InitializeForNewTrack()
74 fCheckedTracks.clear();
87 G4cout <<
"________________________________________________________________"
90 G4cout <<
"G4DNAIndependentReactionTimeStepper::CalculateStep" <<
G4endl;
91 G4cout <<
"Check done for molecule : " << pMoleculeA->GetName() <<
" (" << trackA.
GetTrackID()
96 auto pMolConfA = pMoleculeA->GetMolecularConfiguration();
98 const auto pReactantList = fMolecularReactionTable->CanReactWith(pMolConfA);
100 if (pReactantList ==
nullptr) {
103 msg <<
"G4DNAIndependentReactionTimeStepper::CalculateStep will return infinity "
104 "for the reaction because the molecule "
105 << pMoleculeA->GetName() <<
" does not have any reactants given in the reaction table."
107 G4Exception(
"G4DNAIndependentReactionTimeStepper::CalculateStep",
108 "G4DNAIndependentReactionTimeStepper03",
JustWarning, msg);
113 auto nbReactives = (
G4int)pReactantList->size();
115 if (nbReactives == 0) {
118 msg <<
"G4DNAIndependentReactionTimeStepper::CalculateStep will "
120 "for the reaction because the molecule "
121 << pMoleculeA->GetName() <<
" does not have any reactants given in the reaction table."
122 <<
"This message can also result from a wrong implementation of "
123 "the reaction table."
125 G4Exception(
"G4DNAIndependentReactionTimeStepper::CalculateStep",
126 "G4DNAIndependentReactionTimeStepper04",
JustWarning, msg);
130 fReactionModel->Initialise(pMolConfA, trackA);
131 for (
G4int i = 0; i < nbReactives; ++i) {
132 auto pMoleculeB = (*pReactantList)[i];
133 G4int key = pMoleculeB->GetMoleculeID();
137 const G4double Reff = fReactionModel->GetReactionRadius(i);
138 std::vector<std::pair<G4TrackList::iterator, G4double>> resultIndices;
139 resultIndices.clear();
142 if (resultIndices.empty()) {
145 for (
auto& it : resultIndices) {
146 G4Track* pTrackB = *(std::get<0>(it));
148 if (pTrackB == &trackA) {
151 if (pTrackB ==
nullptr) {
153 exceptionDescription <<
"No trackB no valid";
155 "G4DNAIndependentReactionTimeStepper"
157 "G4DNAIndependentReactionTimeStepper007",
FatalException, exceptionDescription);
159 if (fCheckedTracks.find(pTrackB->
GetTrackID()) != fCheckedTracks.end()) {
163 Utils utils(trackA, *pTrackB);
165 auto pMolConfB = pMolB->GetMolecularConfiguration();
167 if (distance * distance < Reff * Reff) {
168 auto reactionData = fMolecularReactionTable->GetReactionData(pMolConfA, pMolConfB);
176 G4double tempMinET = GetTimeToEncounter(trackA, *pTrackB);
196void G4DNAIndependentReactionTimeStepper::CheckAndRecordResults(
G4double reactionTime,
199 if (utils.fpTrackB->GetTrackStatus() !=
fAlive) {
203 if (&utils.fpTrackB == &utils.fpTrackA) {
205 msg <<
"A track is reacting with itself"
206 " (which is impossible) ie fpTrackA == trackB"
208 msg <<
"Molecule A is of type : " << utils.fpMoleculeA->GetName()
209 <<
" with trackID : " << utils.fpTrackA->GetTrackID()
210 <<
" and B : " << utils.fpMoleculeB->GetName()
211 <<
" with trackID : " << utils.fpTrackB->GetTrackID() <<
G4endl;
212 G4Exception(
"G4DNAIndependentReactionTimeStepper::RetrieveResults",
216 if (fabs(utils.fpTrackB->GetGlobalTime() - utils.fpTrackA->GetGlobalTime())
217 > utils.fpTrackA->GetGlobalTime() * (1. - 1. / 100))
221 msg <<
"The interacting tracks are not synchronized in time" <<
G4endl;
222 msg <<
"trackB->GetGlobalTime() != fpTrackA.GetGlobalTime()" <<
G4endl;
224 msg <<
"fpTrackA : trackID : " << utils.fpTrackA->GetTrackID()
225 <<
"\t Name :" << utils.fpMoleculeA->GetName()
226 <<
"\t fpTrackA->GetGlobalTime() = " <<
G4BestUnit(utils.fpTrackA->GetGlobalTime(),
"Time")
229 msg <<
"trackB : trackID : " << utils.fpTrackB->GetTrackID()
230 <<
"\t Name :" << utils.fpMoleculeB->GetName()
231 <<
"\t trackB->GetGlobalTime() = " <<
G4BestUnit(utils.fpTrackB->GetGlobalTime(),
"Time")
234 G4Exception(
"G4DNAIndependentReactionTimeStepper::RetrieveResults",
237 if (reactionTime < 0) {
240 msg <<
"The interacting tracks are not in good time" <<
G4endl;
242 msg <<
"fpTrackA : trackID : " << utils.fpTrackA->GetTrackID()
243 <<
"\t Name :" << utils.fpMoleculeA->GetName()
244 <<
"\t fpTrackA->GetGlobalTime() = " <<
G4BestUnit(utils.fpTrackA->GetGlobalTime(),
"Time")
247 msg <<
"trackB : trackID : " << utils.fpTrackB->GetTrackID()
248 <<
"\t Name :" << utils.fpMoleculeB->GetName()
249 <<
"\t trackB->GetGlobalTime() = " <<
G4BestUnit(utils.fpTrackB->GetGlobalTime(),
"Time")
252 G4Exception(
"G4DNAIndependentReactionTimeStepper::CheckAndRecordResults",
258 fReactionSet->AddReaction(reactionTime + globalTime, utils.fpTrackA, utils.fpTrackB);
259 fSampledPositions[utils.fpTrackA->GetTrackID()] = utils.fpTrackA->GetPosition();
260 fSampledPositions[utils.fpTrackB->GetTrackID()] = utils.fpTrackB->GetPosition();
266 if (pReactionSet ==
nullptr) {
271 if (reactionPerTime.empty()) {
274 for (
auto reaction_i = reactionPerTime.begin(); reaction_i != reactionPerTime.end();
275 reaction_i = reactionPerTime.begin())
277 G4Track* pTrackA = (*reaction_i)->GetReactants().first;
282 G4Track* pTrackB = (*reaction_i)->GetReactant(pTrackA);
288 if (pTrackB == pTrackA) {
290 msg <<
"The IT reaction process sent back a reaction "
291 "between trackA and trackB. ";
292 msg <<
"The problem is trackA == trackB";
293 G4Exception(
"G4DNAIndependentReactionTimeStepper::FindReaction",
296 G4double reactionTime = (*reaction_i)->GetTime();
297 currentStepTime = reactionTime - globalTime;
299 G4cout <<
" reaction Time : " << reactionTime <<
" currentStepTime : " << currentStepTime
300 <<
" globalTime : " << globalTime <<
" " << pTrackA->
GetTrackID() <<
" + "
304 if (fpReactionProcess !=
nullptr) {
305 if ((fSampledPositions.find(pTrackA->
GetTrackID()) == fSampledPositions.end()
306 && (fSampledPositions.find(pTrackB->
GetTrackID()) == fSampledPositions.end())))
309 msg <<
"The positions of trackA and trackB have no counted ";
310 G4Exception(
"G4DNAIndependentReactionTimeStepper::FindReaction",
316 auto pReactionChange = fpReactionProcess->MakeReaction(*pTrackA, *pTrackB);
317 if (pReactionChange ==
nullptr) {
320 G4int nbSecondaries = pReactionChange->GetNumberOfSecondaries();
321 if (nbSecondaries > 0) {
322 const std::vector<G4Track*>* productsVector = pReactionChange->GetfSecondary();
323 for (
const auto& it : *productsVector) {
324 fSecondaries.push_back(it);
327 return pReactionChange;
335 fReactionModel = pReactionModel;
340 return fReactionModel;
348G4double G4DNAIndependentReactionTimeStepper::GetTimeToEncounter(
const G4Track& trackA,
352 ->GetTimeToEncounter(trackA, trackB);
353 return timeToReaction;
358 fpReactionProcess = pReactionProcess;
365 if (!fIsInitialized) {
366 InitializeReactions(currentGlobalTime);
369 G4int nbPreviousSecondaries = (
G4int)fSecondaries.size();
370 if (nbPreviousSecondaries > 0) {
371 InitializeForNewTrack();
372 for (
const auto& it : fSecondaries) {
375 fSecondaries.clear();
377 fTSTimeStep = GetNextReactionTime() - currentGlobalTime;
378 if (fTSTimeStep < 0) {
380 msg <<
"fTSTimeStep < 0" <<
": fTSTimeStep : " << fTSTimeStep
381 <<
" GetNextReactionTime() : " << GetNextReactionTime()
382 <<
" currentGlobalTime : " << currentGlobalTime <<
G4endl;
383 G4Exception(
"G4DNAIndependentReactionTimeStepper::CalculateMinTimeStep",
389void G4DNAIndependentReactionTimeStepper::InitializeReactions(
G4double )
391 fCheckedTracks.clear();
392 for (
auto pTrack : *fpTrackContainer->
GetMainList()) {
393 if (pTrack ==
nullptr) {
395 msg <<
"No track found.";
396 G4Exception(
"G4DNAIndependentReactionTimeStepper::InitializeReactions",
408 G4cout <<
"InitializeReactions : reaction events : "
409 << fReactionSet->GetReactionsPerTime().size() <<
". The previous time step : "
411 fIsInitialized =
true;
414G4double G4DNAIndependentReactionTimeStepper::GetNextReactionTime()
417 auto nextReaction = GetNextReaction();
418 if (nextReaction !=
nullptr) {
419 output = GetNextReaction()->GetTime();
424const G4ITReaction* G4DNAIndependentReactionTimeStepper::GetNextReaction()
426 G4ITReaction* output =
nullptr;
428 auto reaction_i = reactionPerTime.begin();
429 if (reaction_i != reactionPerTime.end()) {
430 output = (reaction_i->get());
#define BuildChemicalMoleculeFinder()
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
std::multiset< G4ITReactionPtr, compReactionPerTime > G4ITReactionPerTime
G4Molecule * GetMolecule(const G4Track &track)
G4GLOB_DLL std::ostream G4cout
G4double CalculateStep(const G4Track &, const G4double &) override
G4DNAIndependentReactionTimeStepper()
std::unique_ptr< G4ITReactionChange > FindReaction(G4ITReactionSet *pReactionSet, G4double ¤tStepTime, const G4double globalTime)
G4VDNAReactionModel * GetReactionModel()
void SetReactionModel(G4VDNAReactionModel *)
G4double CalculateMinTimeStep(G4double, G4double) override
void SetReactionProcess(G4VITReactionProcess *pReactionProcess)
static G4double GetRCutOff()
void SelectThisReaction(G4ITReactionPtr reaction)
G4ITReactionPerTime & GetReactionsPerTime()
G4TrackList * GetMainList(Key)
static G4OctreeFinder * Instance()
void FindNearestInRange(const G4Track &track, const int &key, G4double R, std::vector< std::pair< typename CONTAINER::iterator, G4double > > &result, G4bool isSort=false) const
static G4Scheduler * Instance()
G4double GetGlobalTime() const override
G4TrackStatus GetTrackStatus() const
void SetPosition(const G4ThreeVector &aValue)
const G4ThreeVector & GetPosition() const
static G4ThreadLocal G4double fUserMinTimeStep
G4double fSampledMinTimeStep