Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4DNAIndependentReactionTimeStepper.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25// 20/2/2019
26// Author: HoangTRAN
27
29
32#include "G4DNAMakeReaction.hh"
35#include "G4IRTUtils.hh"
36#include "G4ITReactionChange.hh"
37#include "G4Molecule.hh"
38#include "G4Scheduler.hh"
39#include "G4UnitsTable.hh"
41#include "Randomize.hh"
42
43#include <memory>
44using namespace std;
45using namespace CLHEP;
46
47G4DNAIndependentReactionTimeStepper::Utils::Utils(const G4Track& trackA, const G4Track& trackB)
48 : fpTrackA(const_cast<G4Track*>(&trackA)), fpTrackB(const_cast<G4Track*>(&trackB))
49{
50 fpMoleculeA = GetMolecule(trackA);
51 fpMoleculeB = GetMolecule(trackB);
52 fUserMinTimeStep = 1 * CLHEP::ps;
53}
54
59
61{
62 //fVerbose = G4Scheduler::Instance()->GetVerbose();
63 if (G4Scheduler::Instance()->IsInteractionStep()) {
64 fReactionSet->CleanAllReaction();
65 fIsInitialized = false;
66 fSampledPositions.clear();
67 fSecondaries.clear();
68 InitializeForNewTrack();
69 }
70}
71
72void G4DNAIndependentReactionTimeStepper::InitializeForNewTrack()
73{
74 fCheckedTracks.clear();
76}
77
79 const G4double& /*userMinTimeStep*/)
80{
81 auto pMoleculeA = GetMolecule(trackA);
83 fCheckedTracks.insert(trackA.GetTrackID());
84
85#ifdef G4VERBOSE
86 if (fVerbose > 1) {
87 G4cout << "________________________________________________________________"
88 "_______"
89 << G4endl;
90 G4cout << "G4DNAIndependentReactionTimeStepper::CalculateStep" << G4endl;
91 G4cout << "Check done for molecule : " << pMoleculeA->GetName() << " (" << trackA.GetTrackID()
92 << ") " << G4endl;
93 }
94#endif
95
96 auto pMolConfA = pMoleculeA->GetMolecularConfiguration();
97
98 const auto pReactantList = fMolecularReactionTable->CanReactWith(pMolConfA);
99
100 if (pReactantList == nullptr) {
101 if (fVerbose > 1) {
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."
106 << G4endl;
107 G4Exception("G4DNAIndependentReactionTimeStepper::CalculateStep",
108 "G4DNAIndependentReactionTimeStepper03", JustWarning, msg);
109 }
110 return DBL_MAX;
111 }
112
113 auto nbReactives = (G4int)pReactantList->size();
114
115 if (nbReactives == 0) {
116 if (fVerbose > 1) {
118 msg << "G4DNAIndependentReactionTimeStepper::CalculateStep will "
119 "return infinity "
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."
124 << G4endl;
125 G4Exception("G4DNAIndependentReactionTimeStepper::CalculateStep",
126 "G4DNAIndependentReactionTimeStepper04", JustWarning, msg);
127 }
128 return DBL_MAX;
129 }
130 fReactionModel->Initialise(pMolConfA, trackA);
131 for (G4int i = 0; i < nbReactives; ++i) {
132 auto pMoleculeB = (*pReactantList)[i];
133 G4int key = pMoleculeB->GetMoleculeID();
134 fRCutOff = G4IRTUtils::GetRCutOff();
135 //______________________________________________________________
136 // Retrieve reaction range
137 const G4double Reff = fReactionModel->GetReactionRadius(i);
138 std::vector<std::pair<G4TrackList::iterator, G4double>> resultIndices;
139 resultIndices.clear();
140 G4ChemicalMoleculeFinder::Instance()->FindNearestInRange(trackA, key, fRCutOff, resultIndices);
141
142 if (resultIndices.empty()) {
143 continue;
144 }
145 for (auto& it : resultIndices) {
146 G4Track* pTrackB = *(std::get<0>(it));
147
148 if (pTrackB == &trackA) {
149 continue;
150 }
151 if (pTrackB == nullptr) {
152 G4ExceptionDescription exceptionDescription;
153 exceptionDescription << "No trackB no valid";
155 "G4DNAIndependentReactionTimeStepper"
156 "::CalculateStep()",
157 "G4DNAIndependentReactionTimeStepper007", FatalException, exceptionDescription);
158 }
159 if (fCheckedTracks.find(pTrackB->GetTrackID()) != fCheckedTracks.end()) {
160 continue;
161 }
162
163 Utils utils(trackA, *pTrackB);
164 auto pMolB = GetMolecule(pTrackB);
165 auto pMolConfB = pMolB->GetMolecularConfiguration();
166 G4double distance = (trackA.GetPosition() - pTrackB->GetPosition()).mag();
167 if (distance * distance < Reff * Reff) {
168 auto reactionData = fMolecularReactionTable->GetReactionData(pMolConfA, pMolConfB);
169 if (G4Scheduler::Instance()->GetGlobalTime() == G4Scheduler::Instance()->GetStartTime()) {
170 if (reactionData->GetProbability() > G4UniformRand()) {
172 }
173 }
174 }
175 else {
176 G4double tempMinET = GetTimeToEncounter(trackA, *pTrackB);
177 if (tempMinET < 0 || tempMinET > G4Scheduler::Instance()->GetEndTime()) {
178 continue;
179 }
180 fSampledMinTimeStep = tempMinET;
181 // Fixed the IRT_syn model (Stepper) to ensure it does not use minTimeStep (default = 1 ps)
182 // when DNA reactions do not yet share
183 // the same minTimeStep(The MinTimeStep is used to optimize the chemistry).
184 // TODO: full test
185
186 //if (tempMinET < fUserMinTimeStep) {
187 // fSampledMinTimeStep = fUserMinTimeStep;
188 //}
189 }
190 CheckAndRecordResults(fSampledMinTimeStep, utils);
191 }
192 }
193 return fSampledMinTimeStep;
194}
195
196void G4DNAIndependentReactionTimeStepper::CheckAndRecordResults(G4double reactionTime,
197 const Utils& utils)
198{
199 if (utils.fpTrackB->GetTrackStatus() != fAlive) {
200 return;
201 }
202
203 if (&utils.fpTrackB == &utils.fpTrackA) {
205 msg << "A track is reacting with itself"
206 " (which is impossible) ie fpTrackA == trackB"
207 << G4endl;
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",
213 "G4DNAIndependentReactionTimeStepper003", FatalErrorInArgument, msg);
214 }
215
216 if (fabs(utils.fpTrackB->GetGlobalTime() - utils.fpTrackA->GetGlobalTime())
217 > utils.fpTrackA->GetGlobalTime() * (1. - 1. / 100))
218 {
219 // DEBUG
221 msg << "The interacting tracks are not synchronized in time" << G4endl;
222 msg << "trackB->GetGlobalTime() != fpTrackA.GetGlobalTime()" << G4endl;
223
224 msg << "fpTrackA : trackID : " << utils.fpTrackA->GetTrackID()
225 << "\t Name :" << utils.fpMoleculeA->GetName()
226 << "\t fpTrackA->GetGlobalTime() = " << G4BestUnit(utils.fpTrackA->GetGlobalTime(), "Time")
227 << G4endl;
228
229 msg << "trackB : trackID : " << utils.fpTrackB->GetTrackID()
230 << "\t Name :" << utils.fpMoleculeB->GetName()
231 << "\t trackB->GetGlobalTime() = " << G4BestUnit(utils.fpTrackB->GetGlobalTime(), "Time")
232 << G4endl;
233
234 G4Exception("G4DNAIndependentReactionTimeStepper::RetrieveResults",
235 "G4DNAIndependentReactionTimeStepper004", FatalErrorInArgument, msg);
236 }
237 if (reactionTime < 0) {
238 // DEBUG
240 msg << "The interacting tracks are not in good time" << G4endl;
241
242 msg << "fpTrackA : trackID : " << utils.fpTrackA->GetTrackID()
243 << "\t Name :" << utils.fpMoleculeA->GetName()
244 << "\t fpTrackA->GetGlobalTime() = " << G4BestUnit(utils.fpTrackA->GetGlobalTime(), "Time")
245 << G4endl;
246
247 msg << "trackB : trackID : " << utils.fpTrackB->GetTrackID()
248 << "\t Name :" << utils.fpMoleculeB->GetName()
249 << "\t trackB->GetGlobalTime() = " << G4BestUnit(utils.fpTrackB->GetGlobalTime(), "Time")
250 << G4endl;
251
252 G4Exception("G4DNAIndependentReactionTimeStepper::CheckAndRecordResults",
253 "G4DNAIndependentReactionTimeStepper1", FatalErrorInArgument, msg);
254 }
255
257
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();
261}
262
263std::unique_ptr<G4ITReactionChange> G4DNAIndependentReactionTimeStepper::FindReaction(
264 G4ITReactionSet* pReactionSet, G4double& currentStepTime, const G4double globalTime)
265{
266 if (pReactionSet == nullptr) {
267 return nullptr;
268 }
269
270 G4ITReactionPerTime& reactionPerTime = pReactionSet->GetReactionsPerTime();
271 if (reactionPerTime.empty()) {
272 return nullptr;
273 }
274 for (auto reaction_i = reactionPerTime.begin(); reaction_i != reactionPerTime.end();
275 reaction_i = reactionPerTime.begin())
276 {
277 G4Track* pTrackA = (*reaction_i)->GetReactants().first;
278 currentStepTime = DBL_MAX;
279 if (pTrackA->GetTrackStatus() == fStopAndKill) {
280 continue;
281 }
282 G4Track* pTrackB = (*reaction_i)->GetReactant(pTrackA);
283 currentStepTime = DBL_MAX;
284 if (pTrackB->GetTrackStatus() == fStopAndKill) {
285 continue;
286 }
287
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",
294 "G4DNAIndependentReactionTimeStepper02", FatalErrorInArgument, msg);
295 }
296 G4double reactionTime = (*reaction_i)->GetTime();
297 currentStepTime = reactionTime - globalTime;
298 if(fVerbose > 1)
299 G4cout << " reaction Time : " << reactionTime << " currentStepTime : " << currentStepTime
300 << " globalTime : " << globalTime << " " << pTrackA->GetTrackID() << " + "
301 << pTrackB->GetTrackID() << G4endl;
302
303 pReactionSet->SelectThisReaction(*reaction_i);
304 if (fpReactionProcess != nullptr) {
305 if ((fSampledPositions.find(pTrackA->GetTrackID()) == fSampledPositions.end()
306 && (fSampledPositions.find(pTrackB->GetTrackID()) == fSampledPositions.end())))
307 {
309 msg << "The positions of trackA and trackB have no counted ";
310 G4Exception("G4DNAIndependentReactionTimeStepper::FindReaction",
311 "G4DNAIndependentReactionTimeStepper0001", FatalErrorInArgument, msg);
312 }
313
314 pTrackA->SetPosition(fSampledPositions[pTrackA->GetTrackID()]);
315 pTrackB->SetPosition(fSampledPositions[pTrackB->GetTrackID()]);
316 auto pReactionChange = fpReactionProcess->MakeReaction(*pTrackA, *pTrackB);
317 if (pReactionChange == nullptr) {
318 return nullptr;
319 }
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);
325 }
326 }
327 return pReactionChange;
328 }
329 }
330 return nullptr;
331}
332
334{
335 fReactionModel = pReactionModel;
336}
337
342
344{
345 fVerbose = flag;
346}
347
348G4double G4DNAIndependentReactionTimeStepper::GetTimeToEncounter(const G4Track& trackA,
349 const G4Track& trackB)
350{
351 G4double timeToReaction = dynamic_cast<G4DiffusionControlledReactionModel*>(fReactionModel)
352 ->GetTimeToEncounter(trackA, trackB);
353 return timeToReaction;
354}
355
357{
358 fpReactionProcess = pReactionProcess;
359}
361 G4double /*definedMinTimeStep*/)
362{
363 G4double fTSTimeStep = DBL_MAX;
364 // fUserMinTimeStep = definedMinTimeStep;
365 if (!fIsInitialized) {
366 InitializeReactions(currentGlobalTime);
367 }
368
369 G4int nbPreviousSecondaries = (G4int)fSecondaries.size();
370 if (nbPreviousSecondaries > 0) {
371 InitializeForNewTrack();
372 for (const auto& it : fSecondaries) {
374 }
375 fSecondaries.clear();
376 }
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",
384 "G4DNAIndependentReactionTimeStepper002", FatalErrorInArgument, msg);
385 }
386 return fTSTimeStep;
387}
388
389void G4DNAIndependentReactionTimeStepper::InitializeReactions(G4double /*currentGlobalTime*/)
390{
391 fCheckedTracks.clear();
392 for (auto pTrack : *fpTrackContainer->GetMainList()) {
393 if (pTrack == nullptr) {
395 msg << "No track found.";
396 G4Exception("G4DNAIndependentReactionTimeStepper::InitializeReactions",
397 "G4DNAIndependentReactionTimeStepper030", FatalErrorInArgument, msg);
398 continue;
399 }
400
401 G4TrackStatus trackStatus = pTrack->GetTrackStatus();
402 if (trackStatus == fStopAndKill || trackStatus == fStopButAlive) {
403 continue;
404 }
406 }
407 if (fVerbose > 0)
408 G4cout << "InitializeReactions : reaction events : "
409 << fReactionSet->GetReactionsPerTime().size() << ". The previous time step : "
410 << G4BestUnit(G4Scheduler::Instance()->GetPreviousTimeStep(), "Time") << G4endl;
411 fIsInitialized = true;
412}
413
414G4double G4DNAIndependentReactionTimeStepper::GetNextReactionTime()
415{
416 G4double output = DBL_MAX;
417 auto nextReaction = GetNextReaction();
418 if (nextReaction != nullptr) {
419 output = GetNextReaction()->GetTime();
420 }
421 return output;
422}
423
424const G4ITReaction* G4DNAIndependentReactionTimeStepper::GetNextReaction()
425{
426 G4ITReaction* output = nullptr;
427 G4ITReactionPerTime& reactionPerTime = fReactionSet->GetReactionsPerTime();
428 auto reaction_i = reactionPerTime.begin();
429 if (reaction_i != reactionPerTime.end()) {
430 output = (reaction_i->get());
431 }
432 return output;
433}
#define BuildChemicalMoleculeFinder()
@ JustWarning
@ FatalException
@ FatalErrorInArgument
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)
Definition G4Molecule.cc:75
#define G4BestUnit(a, b)
G4TrackStatus
@ fAlive
@ fStopAndKill
@ fStopButAlive
double G4double
Definition G4Types.hh:83
int G4int
Definition G4Types.hh:85
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition Randomize.hh:52
G4double CalculateStep(const G4Track &, const G4double &) override
std::unique_ptr< G4ITReactionChange > FindReaction(G4ITReactionSet *pReactionSet, G4double &currentStepTime, const G4double globalTime)
G4double CalculateMinTimeStep(G4double, G4double) override
void SetReactionProcess(G4VITReactionProcess *pReactionProcess)
static G4double GetRCutOff()
Definition G4IRTUtils.cc:39
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)
G4int GetTrackID() const
const G4ThreeVector & GetPosition() const
static G4ThreadLocal G4double fUserMinTimeStep
#define DBL_MAX
Definition templates.hh:62