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