Geant4 11.2.2
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
28#include <memory>
32#include "G4UnitsTable.hh"
33#include "G4Molecule.hh"
36#include "G4DNAMakeReaction.hh"
37#include "G4ITReactionChange.hh"
38#include "G4Scheduler.hh"
39#include "G4IRTUtils.hh"
40#include "Randomize.hh"
42using namespace std;
43using namespace CLHEP;
44
45G4DNAIndependentReactionTimeStepper::Utils::Utils(const G4Track& trackA,
46 const G4Track& trackB)
47 : fTrackA(trackA)
48 , fTrackB(trackB)
49{
50 fpMoleculeA = GetMolecule(trackA);
51 fpMoleculeB = GetMolecule(trackA);
52}
53
58
65
66void G4DNAIndependentReactionTimeStepper::InitializeForNewTrack()
67{
68 if(fReactants != nullptr)
69 {
70 fReactants.reset();
71 }
73 fHasAlreadyReachedNullTime = false;
74}
75
77 const G4Track& trackA, const G4double& userMinTimeStep)
78{
79 auto pMoleculeA = GetMolecule(trackA);
80 InitializeForNewTrack();
81 fUserMinTimeStep = userMinTimeStep;
82 fCheckedTracks.insert(trackA.GetTrackID());
83
84#ifdef G4VERBOSE
85 if(fVerbose != 0)
86 {
87 G4cout << "________________________________________________________________"
88 "_______"
89 << G4endl;
90 G4cout << "G4DNAIndependentReactionTimeStepper::CalculateStep" << G4endl;
91 G4cout << "Check done for molecule : " << pMoleculeA->GetName() << " ("
92 << trackA.GetTrackID() << ") " << G4endl;
93 }
94#endif
95
96 auto pMolConfA = pMoleculeA->GetMolecularConfiguration();
97
98 const auto pReactantList = fMolecularReactionTable->CanReactWith(pMolConfA);
99
100 if(pReactantList == nullptr)
101 {
102#ifdef G4VERBOSE
103 if(fVerbose > 1)
104 {
105 G4cout << "!!!!!!!!!!!!!!!!!!!!" << G4endl;
106 G4cout << "!!! WARNING" << G4endl;
107 G4cout << "G4DNAIndependentReactionTimeStepper::CalculateStep will "
108 "return infinity "
109 "for the reaction because the molecule "
110 << pMoleculeA->GetName()
111 << " does not have any reactants given in the reaction table."
112 << G4endl;
113 G4cout << "!!!!!!!!!!!!!!!!!!!!" << G4endl;
114 }
115#endif
116 return DBL_MAX;
117 }
118
119 auto nbReactives = (G4int)pReactantList->size();
120
121 if(nbReactives == 0)
122 {
123#ifdef G4VERBOSE
124 // DEBUG
125 if(fVerbose != 0)
126 {
127 G4cout << "!!!!!!!!!!!!!!!!!!!!" << G4endl;
128 G4cout << "!!! WARNING" << G4endl;
129 G4cout << "G4DNAIndependentReactionTimeStepper::CalculateStep will "
130 "return infinity "
131 "for the reaction because the molecule "
132 << pMoleculeA->GetName()
133 << " does not have any reactants given in the reaction table."
134 << "This message can also result from a wrong implementation of "
135 "the reaction table."
136 << G4endl;
137 G4cout << "!!!!!!!!!!!!!!!!!!!!" << G4endl;
138 }
139#endif
140 return DBL_MAX;
141 }
142 fReactants = std::make_shared<vector<G4Track*>>();
143 fReactionModel->Initialise(pMolConfA, trackA);
144 for(G4int i = 0; i < nbReactives; ++i)
145 {
146 auto pMoleculeB = (*pReactantList)[i];
147 G4int key = pMoleculeB->GetMoleculeID();
148
149 // fRCutOff = G4IRTUtils::GetRCutOff(1 * ps);
150 fRCutOff = G4IRTUtils::GetRCutOff();
151 //______________________________________________________________
152 // Retrieve reaction range
153 const G4double Reff = fReactionModel->GetReactionRadius(i);
154 std::vector<std::pair<G4TrackList::iterator, G4double>> resultIndices;
155 resultIndices.clear();
157 trackA, key, fRCutOff, resultIndices);
158
159 if(resultIndices.empty())
160 {
161 continue;
162 }
163 for(auto& it : resultIndices)
164 {
165 G4Track* pTrackB = *(std::get<0>(it));
166
167 if(pTrackB == &trackA)
168 {
169 continue;
170 }
171 if(pTrackB == nullptr)
172 {
173 G4ExceptionDescription exceptionDescription;
174 exceptionDescription << "No trackB no valid";
175 G4Exception("G4DNAIndependentReactionTimeStepper"
176 "::CalculateStep()",
177 "G4DNAIndependentReactionTimeStepper007", FatalException,
178 exceptionDescription);
179 }else
180 {
181 if(fCheckedTracks.find(pTrackB->GetTrackID()) != fCheckedTracks.end())
182 {
183 continue;
184 }
185
186 Utils utils(trackA, *pTrackB);
187
188 auto pMolB = GetMolecule(pTrackB);
189 auto pMolConfB = pMolB->GetMolecularConfiguration();
190 G4double distance = (trackA.GetPosition() - pTrackB->GetPosition()).mag();
191 if(distance * distance < Reff * Reff)
192 {
193 auto reactionData =
194 fMolecularReactionTable->GetReactionData(pMolConfA, pMolConfB);
195 if(G4Scheduler::Instance()->GetGlobalTime() == G4Scheduler::Instance()->GetStartTime())
196 {
197 if(reactionData->GetProbability() > G4UniformRand())
198 {
199 if(!fHasAlreadyReachedNullTime)
200 {
201 fReactants->clear();
202 fHasAlreadyReachedNullTime = true;
203 }
205 CheckAndRecordResults(utils);
206 }
207 }
208 }
209 else
210 {
211 G4double tempMinET = GetTimeToEncounter(trackA, *pTrackB);
212 if(tempMinET < 0 || tempMinET > G4Scheduler::Instance()->GetEndTime())
213 {
214 continue;
215 }
216 if(tempMinET >= fSampledMinTimeStep)
217 {
218 continue;
219 }
220 fSampledMinTimeStep = tempMinET;
221 fReactants->clear();
222 CheckAndRecordResults(utils);
223 }
224 }
225 }
226 }
227
228#ifdef G4VERBOSE
229 if(fVerbose != 0)
230 {
231 G4cout << "G4DNAIndependentReactionTimeStepper::CalculateStep will finally "
232 "return :"
234
235 if(fVerbose > 1)
236 {
237 G4cout << "Selected reactants for trackA: " << pMoleculeA->GetName()
238 << " (" << trackA.GetTrackID() << ") are: ";
239
240 vector<G4Track*>::iterator it;
241 for(it = fReactants->begin(); it != fReactants->end(); it++)
242 {
243 G4Track* trackB = *it;
244 G4cout << GetMolecule(trackB)->GetName() << " (" << trackB->GetTrackID()
245 << ") \t ";
246 }
247 G4cout << G4endl;
248 }
249 }
250#endif
251 return fSampledMinTimeStep;
252}
253
254void G4DNAIndependentReactionTimeStepper::CheckAndRecordResults(
255 const Utils& utils)
256{
257 if(utils.fTrackB.GetTrackStatus() != fAlive)
258 {
259 return;
260 }
261
262 if(&utils.fTrackB == &utils.fTrackA)
263 {
264 G4ExceptionDescription exceptionDescription;
265 exceptionDescription << "A track is reacting with itself"
266 " (which is impossible) ie fpTrackA == trackB"
267 << G4endl;
268 exceptionDescription << "Molecule A is of type : "
269 << utils.fpMoleculeA->GetName()
270 << " with trackID : " << utils.fTrackA.GetTrackID()
271 << " and B : " << utils.fpMoleculeB->GetName()
272 << " with trackID : " << utils.fTrackB.GetTrackID()
273 << G4endl;
274 G4Exception("G4DNAIndependentReactionTimeStepper::RetrieveResults",
275 "G4DNAIndependentReactionTimeStepper003", FatalErrorInArgument,
276 exceptionDescription);
277 }
278
279 if(fabs(utils.fTrackB.GetGlobalTime() - utils.fTrackA.GetGlobalTime()) >
280 utils.fTrackA.GetGlobalTime() * (1. - 1. / 100))
281 {
282 // DEBUG
283 G4ExceptionDescription exceptionDescription;
284 exceptionDescription
285 << "The interacting tracks are not synchronized in time" << G4endl;
286 exceptionDescription
287 << "trackB->GetGlobalTime() != fpTrackA.GetGlobalTime()" << G4endl;
288
289 exceptionDescription << "fpTrackA : trackID : "
290 << utils.fTrackA.GetTrackID()
291 << "\t Name :" << utils.fpMoleculeA->GetName()
292 << "\t fpTrackA->GetGlobalTime() = "
293 << G4BestUnit(utils.fTrackA.GetGlobalTime(), "Time")
294 << G4endl;
295
296 exceptionDescription << "trackB : trackID : " << utils.fTrackB.GetTrackID()
297 << "\t Name :" << utils.fpMoleculeB->GetName()
298 << "\t trackB->GetGlobalTime() = "
299 << G4BestUnit(utils.fTrackB.GetGlobalTime(), "Time")
300 << G4endl;
301
302 G4Exception("G4DNAIndependentReactionTimeStepper::RetrieveResults",
303 "G4DNAIndependentReactionTimeStepper004", FatalErrorInArgument,
304 exceptionDescription);
305 }
306 fReactants->push_back(const_cast<G4Track*>(&utils.fTrackB));
307}
308
309std::unique_ptr<G4ITReactionChange>
311 G4ITReactionSet* pReactionSet, const G4double& currentStepTime,
312 const G4double& /*previousStepTime*/,
313 const G4bool& /*reachedUserStepTimeLimit*/)
314{
315 if(pReactionSet == nullptr)
316 {
317 return nullptr;
318 }
319
320 G4ITReactionPerTime& reactionPerTime = pReactionSet->GetReactionsPerTime();
321 if(reactionPerTime.empty())
322 {
323 return nullptr;
324 }
325
326 for(auto reaction_i = reactionPerTime.begin();
327 reaction_i != reactionPerTime.end(); reaction_i = reactionPerTime.begin())
328 {
329 G4Track* pTrackA = (*reaction_i)->GetReactants().first;
330 if(pTrackA->GetTrackStatus() == fStopAndKill)
331 {
332 continue;
333 }
334 G4Track* pTrackB = (*reaction_i)->GetReactant(pTrackA);
335 if(pTrackB->GetTrackStatus() == fStopAndKill)
336 {
337 continue;
338 }
339
340 if(pTrackB == pTrackA)
341 {
342 G4ExceptionDescription exceptionDescription;
343 exceptionDescription << "The IT reaction process sent back a reaction "
344 "between trackA and trackB. ";
345 exceptionDescription << "The problem is trackA == trackB";
346 G4Exception("G4DNAIndependentReactionTimeStepper::FindReaction",
347 "G4DNAIndependentReactionTimeStepper02", FatalErrorInArgument,
348 exceptionDescription);
349 }
350 pReactionSet->SelectThisReaction(*reaction_i);
351 if(fpReactionProcess != nullptr &&
352 fpReactionProcess->TestReactibility(*pTrackA, *pTrackB, currentStepTime,
353 false))
354 {
355 if((fSampledPositions.find(pTrackA->GetTrackID()) ==
356 fSampledPositions.end() &&
357 (fSampledPositions.find(pTrackB->GetTrackID()) ==
358 fSampledPositions.end())))
359 {
360 G4ExceptionDescription exceptionDescription;
361 exceptionDescription
362 << "The positions of trackA and trackB have no counted ";
363 G4Exception("G4DNAIndependentReactionTimeStepper::FindReaction",
364 "G4DNAIndependentReactionTimeStepper0001",
365 FatalErrorInArgument, exceptionDescription);
366 }
367
368 pTrackA->SetPosition(fSampledPositions[pTrackA->GetTrackID()]);
369 pTrackB->SetPosition(fSampledPositions[pTrackB->GetTrackID()]);
370 auto pReactionChange =
371 fpReactionProcess->MakeReaction(*pTrackA, *pTrackB);
372 if(pReactionChange == nullptr)
373 {
374 return nullptr;
375 }
376 return pReactionChange;
377 }
378 }
379 return nullptr;
380}
381
383 G4VDNAReactionModel* pReactionModel)
384{
385 fReactionModel = pReactionModel;
386}
387
392
394{
395 fVerbose = flag;
396}
397
398G4double G4DNAIndependentReactionTimeStepper::GetTimeToEncounter(
399 const G4Track& trackA, const G4Track& trackB)
400{
401 G4double timeToReaction =
402 dynamic_cast<G4DiffusionControlledReactionModel*>(fReactionModel)
403 ->GetTimeToEncounter(trackA, trackB);
404 return timeToReaction;
405}
406
408 G4VITReactionProcess* pReactionProcess)
409{
410 fpReactionProcess = pReactionProcess;
411}
413 G4double /*currentGlobalTime*/, G4double definedMinTimeStep)
414{
415 G4double fTSTimeStep = DBL_MAX;
416 fCheckedTracks.clear();
417
418 for(auto pTrack : *fpTrackContainer->GetMainList())
419 {
420 if(pTrack == nullptr)
421 {
422 G4ExceptionDescription exceptionDescription;
423 exceptionDescription << "No track found.";
424 G4Exception("G4DNAIndependentReactionTimeStepper::CalculateMinTimeStep",
425 "G4DNAIndependentReactionTimeStepper006",
426 FatalErrorInArgument, exceptionDescription);
427 continue;
428 }
429
430 G4TrackStatus trackStatus = pTrack->GetTrackStatus();
431 if(trackStatus == fStopAndKill || trackStatus == fStopButAlive)
432 {
433 continue;
434 }
435
436 G4double sampledMinTimeStep = CalculateStep(*pTrack, definedMinTimeStep);
437 G4TrackVectorHandle reactants = GetReactants();
438
439 if(sampledMinTimeStep < fTSTimeStep)
440 {
441 fTSTimeStep = sampledMinTimeStep;
442 fReactionSet->CleanAllReaction();
443 if(reactants)
444 {
445 fReactionSet->AddReactions(fTSTimeStep, const_cast<G4Track*>(pTrack),
446 reactants);
447
448 fSampledPositions[pTrack->GetTrackID()] = pTrack->GetPosition();
449 for(const auto& it : *fReactants)
450 {
451 auto pTrackB = it;
452 // G4cout<<"position : "<<pTrackB->GetTrackID()<<G4endl;
453 fSampledPositions[pTrackB->GetTrackID()] = pTrackB->GetPosition();
454 }
456 }
457 }
458 else if(fTSTimeStep == sampledMinTimeStep && G4bool(reactants))
459 {
460 fReactionSet->AddReactions(fTSTimeStep, const_cast<G4Track*>(pTrack),
461 reactants);
462
463 fSampledPositions[pTrack->GetTrackID()] = pTrack->GetPosition();
464 for(const auto& it : *fReactants)
465 {
466 auto pTrackB = it;
467 // G4cout<<"position : "<<pTrackB->GetTrackID()<<G4endl;
468 fSampledPositions[pTrackB->GetTrackID()] = pTrackB->GetPosition();
469 }
471 }
472 else if(reactants)
473 {
475 }
476 }
477
478 return fTSTimeStep;
479}
#define BuildChemicalMoleculeFinder()
@ FatalException
@ FatalErrorInArgument
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
std::multiset< G4ITReactionPtr, compReactionPerTime > G4ITReactionPerTime
G4shared_ptr< std::vector< G4Track * > > G4TrackVectorHandle
G4Molecule * GetMolecule(const G4Track &track)
Definition G4Molecule.cc:74
#define G4BestUnit(a, b)
G4TrackStatus
@ fAlive
@ fStopAndKill
@ fStopButAlive
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
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
G4double CalculateMinTimeStep(G4double, G4double) override
std::unique_ptr< G4ITReactionChange > FindReaction(G4ITReactionSet *pReactionSet, const G4double &currentStepTime=0, const G4double &previousStepTime=0, const G4bool &reachedUserStepTimeLimit=false)
void SetReactionProcess(G4VITReactionProcess *pReactionProcess)
Data * GetReactionData(Reactant *, Reactant *) const
const ReactantList * CanReactWith(Reactant *) const
static G4double GetRCutOff()
Definition G4IRTUtils.cc:39
void SelectThisReaction(G4ITReactionPtr reaction)
void AddReactions(G4double time, G4Track *trackA, G4TrackVectorHandle reactants)
G4ITReactionPerTime & GetReactionsPerTime()
G4TrackList * GetMainList(Key)
const G4String & GetName() const override
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()
G4TrackStatus GetTrackStatus() const
void SetPosition(const G4ThreeVector &aValue)
G4int GetTrackID() const
const G4ThreeVector & GetPosition() const
virtual void Initialise(const G4MolecularConfiguration *, const G4Track &)
virtual G4double GetReactionRadius(const G4MolecularConfiguration *, const G4MolecularConfiguration *)=0
virtual std::unique_ptr< G4ITReactionChange > MakeReaction(const G4Track &, const G4Track &)=0
virtual G4bool TestReactibility(const G4Track &, const G4Track &, double, bool)=0
G4TrackVectorHandle fReactants
G4TrackVectorHandle GetReactants()
static G4ThreadLocal G4double fUserMinTimeStep
#define DBL_MAX
Definition templates.hh:62