Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/electromagnetic/dna/utils/src/G4DNAChemistryManager.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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 //
 26 //
 27 // Author: Mathieu Karamitros (kara@cenbg.in2p3.fr)
 28 //
 29 // WARNING : This class is released as a prototype.
 30 // It might strongly evolve or even disappear in the next releases.
 31 //
 32 // History:
 33 // -----------
 34 // 10 Oct 2011 M.Karamitros created
 35 //
 36 // -------------------------------------------------------------------
 37 
 38 #include "G4DNAChemistryManager.hh"
 39 
 40 #include "G4AutoLock.hh"
 41 #include "G4DNAMolecularReactionTable.hh"
 42 #include "G4DNAWaterExcitationStructure.hh"
 43 #include "G4DNAWaterIonisationStructure.hh"
 44 #include "G4Electron_aq.hh"
 45 #include "G4GeometryManager.hh"
 46 #include "G4H2O.hh"
 47 #include "G4MolecularConfiguration.hh"
 48 #include "G4Molecule.hh"
 49 #include "G4MoleculeFinder.hh"
 50 #include "G4MoleculeTable.hh"
 51 #include "G4PhysChemIO.hh"
 52 #include "G4Scheduler.hh"
 53 #include "G4StateManager.hh"
 54 #include "G4SystemOfUnits.hh"
 55 #include "G4UIcmdWithABool.hh"
 56 #include "G4UIcmdWithADoubleAndUnit.hh"
 57 #include "G4UIcmdWithAnInteger.hh"
 58 #include "G4UIcmdWithoutParameter.hh"
 59 #include "G4VITTrackHolder.hh"
 60 #include "G4VMoleculeCounter.hh"
 61 #include "G4VUserChemistryList.hh"
 62 #include "G4VUserPulseInfo.hh"
 63 
 64 #include <memory>
 65 
 66 G4DNAChemistryManager* G4DNAChemistryManager::fgInstance = nullptr;
 67 
 68 G4ThreadLocal G4DNAChemistryManager::ThreadLocalData*
 69     G4DNAChemistryManager::fpThreadData = nullptr;
 70 
 71 G4Mutex chemManExistence;
 72 
 73 //------------------------------------------------------------------------------
 74 
 75 G4DNAChemistryManager::ThreadLocalData::ThreadLocalData()
 76 {
 77     fpPhysChemIO = nullptr;
 78     fThreadInitialized = false;
 79 }
 80 
 81 //------------------------------------------------------------------------------
 82 
 83 G4DNAChemistryManager::ThreadLocalData::~ThreadLocalData()
 84 {
 85     fpThreadData = nullptr;
 86 }
 87 
 88 //------------------------------------------------------------------------------
 89 
 90 void G4DNAChemistryManager::SetPhysChemIO(std::unique_ptr<G4VPhysChemIO> pPhysChemIO)
 91 {
 92     fpThreadData->fpPhysChemIO = std::move(pPhysChemIO);
 93 }
 94 
 95 //------------------------------------------------------------------------------
 96 
 97 //------------------------------------------------------------------------------
 98 /*
 99  * The chemistry manager is shared between threads
100  * It is initialized both on the master thread and on the worker threads
101  */
102 //------------------------------------------------------------------------------
103 G4DNAChemistryManager::G4DNAChemistryManager()
104         : 
105          fpChemDNADirectory(new G4UIdirectory("/chem/"))
106         , fpActivateChem(new G4UIcmdWithABool("/chem/activate", this))
107         , fpRunChem(new G4UIcmdWithAnInteger("/chem/run", this))
108         , fpSkipReactionsFromChemList(new G4UIcmdWithoutParameter("/chem/skipReactionsFromChemList", this))
109         , fpScaleForNewTemperature(new G4UIcmdWithADoubleAndUnit("/chem/temperature", this))
110         , fpInitChem(new G4UIcmdWithoutParameter("/chem/init", this))
111         , 
112          fpExcitationLevel(nullptr)
113         , fpIonisationLevel(nullptr)
114         , fpUserChemistryList(nullptr)
115 {
116     fpRunChem->SetParameterName("Number of runs to execute for the chemistry module"
117                                 "(this works when used in standalone", true, true);
118     fpRunChem->SetDefaultValue(1);
119     fpScaleForNewTemperature->SetUnitCategory("Temperature");
120 }
121 
122 //------------------------------------------------------------------------------
123 
124 G4DNAChemistryManager* G4DNAChemistryManager::Instance()
125 {
126     if (fgInstance == nullptr)
127     {
128         G4AutoLock lock(&chemManExistence);
129         if (fgInstance == nullptr) // MT : double check at initialisation
130         {
131             fgInstance = new G4DNAChemistryManager();
132         }
133         lock.unlock();
134     }
135 
136     // make sure thread local data is initialized for all threads
137     if (fpThreadData == nullptr)
138     {
139         fpThreadData = new ThreadLocalData();
140     }
141 
142     assert(fpThreadData != nullptr);
143 
144     return fgInstance;
145 }
146 
147 //------------------------------------------------------------------------------
148 
149 G4DNAChemistryManager* G4DNAChemistryManager::GetInstanceIfExists()
150 {
151     return fgInstance;
152 }
153 
154 //------------------------------------------------------------------------------
155 
156 G4DNAChemistryManager::~G4DNAChemistryManager()
157 {
158     Clear();
159     fgInstance = nullptr;
160 }
161 
162 //------------------------------------------------------------------------------
163 
164 void G4DNAChemistryManager::Clear()
165 {
166     fpIonisationLevel.reset();
167     fpExcitationLevel.reset();
168 
169     if (fpUserChemistryList)
170     {
171         Deregister(*fpUserChemistryList);
172     }
173 
174     fpChemDNADirectory.reset();
175     fpActivateChem.reset();
176     fpRunChem.reset();
177 
178     fpSkipReactionsFromChemList.reset();
179     fpInitChem.reset();
180 
181     if (fpThreadData != nullptr)
182     {
183         delete fpThreadData;
184         fpThreadData = nullptr;
185     }
186 
187     G4DNAMolecularReactionTable::DeleteInstance();
188     G4MolecularConfiguration::DeleteManager();
189     G4VMoleculeCounter::DeleteInstance();
190 }
191 
192 //------------------------------------------------------------------------------
193 
194 void G4DNAChemistryManager::DeleteInstance()
195 {
196     G4AutoLock lock(&chemManExistence);
197 
198     if (fgInstance != nullptr)
199     {
200         G4DNAChemistryManager* pDeleteMe = fgInstance;
201         fgInstance = nullptr;
202         lock.unlock();
203         delete pDeleteMe;
204     }
205     else
206     {
207         G4cerr << "G4DNAChemistryManager already deleted" << G4endl;
208     }
209     lock.unlock();
210 }
211 
212 //------------------------------------------------------------------------------
213 
214 G4bool G4DNAChemistryManager::Notify(G4ApplicationState requestedState)
215 {
216     if (requestedState == G4State_Quit)
217     {
218         if (fVerbose != 0)
219         {
220             G4cout << "G4DNAChemistryManager::Notify ---> received G4State_Quit"
221                    << G4endl;
222         }
223         Clear();
224     }
225     else if (requestedState == G4State_GeomClosed)
226     {
227         fGeometryClosed = true;
228     }
229     else if (requestedState == G4State_Idle)
230     {
231         InitializeThreadSharedData();
232     }
233 
234     return true;
235 }
236 
237 //------------------------------------------------------------------------------
238 
239 void G4DNAChemistryManager::SetNewValue(G4UIcommand* pCommand, G4String value)
240 {
241     if (pCommand == fpActivateChem.get())
242     {
243         SetChemistryActivation(G4UIcmdWithABool::GetNewBoolValue(value));
244     }
245     else if (pCommand == fpRunChem.get())
246     {
247         int nbExec = value.empty() ? 1 : G4UIcommand::ConvertToInt(value);
248         for (int i = 0 ; i < nbExec ; ++i)
249         {
250             Run();
251         }
252     }
253     else if (pCommand == fpSkipReactionsFromChemList.get())
254     {
255         fSkipReactions = true;
256     }
257     else if (pCommand == fpScaleForNewTemperature.get())
258     {
259         SetGlobalTemperature(fpScaleForNewTemperature->ConvertToDimensionedDouble(value));
260     }
261     else if (pCommand == fpInitChem.get())
262     {
263         Initialize();
264         InitializeThread();
265     }
266 }
267 
268 //------------------------------------------------------------------------------
269 
270 G4String G4DNAChemistryManager::GetCurrentValue(G4UIcommand* pCommand)
271 {
272     if (pCommand == fpActivateChem.get())
273     {
274         return G4UIcmdWithABool::ConvertToString(fActiveChemistry);
275     }
276     if (pCommand == fpScaleForNewTemperature.get())
277     {
278         return fpScaleForNewTemperature->ConvertToStringWithBestUnit(G4MolecularConfiguration::GetGlobalTemperature());
279     }
280     if (pCommand == fpSkipReactionsFromChemList.get())
281     {
282         return G4UIcmdWithABool::ConvertToString(fSkipReactions);
283     }
284 
285     return "";
286 }
287 
288 //------------------------------------------------------------------------------
289 
290 void G4DNAChemistryManager::InitializeThreadSharedData()
291 {
292     if (!G4Threading::IsMasterThread())
293     {
294         return;
295     }
296 
297     G4MoleculeTable::Instance()->PrepareMolecularConfiguration();
298     G4MoleculeTable::Instance()->Finalize();
299 }
300 
301 //------------------------------------------------------------------------------
302 void G4DNAChemistryManager::Run()
303 {
304     if (!fActiveChemistry)
305     {
306         return;
307     }
308 
309     InitializeThread();
310 
311     if (!fMasterInitialized)
312     {
313         G4ExceptionDescription description;
314         description << "Global components were not initialized.";
315         G4Exception("G4DNAChemistryManager::Run", "MASTER_INIT", FatalException,
316                     description);
317     }
318 
319     if (!fpThreadData->fThreadInitialized)
320     {
321         G4ExceptionDescription description;
322         description << "Thread local components were not initialized.";
323         G4Exception("G4DNAChemistryManager::Run", "THREAD_INIT", FatalException,
324                     description);
325     }
326     
327     G4MoleculeTable::Instance()->Finalize();
328     G4Scheduler::Instance()->Process();
329     if (fResetCounterWhenRunEnds)
330     {
331         G4VMoleculeCounter::Instance()->ResetCounter();
332     }
333     CloseFile();
334 }
335 
336 //------------------------------------------------------------------------------
337 
338 void G4DNAChemistryManager::UseAsStandalone(G4bool flag)
339 {
340     fUseInStandalone = flag;
341 }
342 
343 //------------------------------------------------------------------------------
344 
345 void G4DNAChemistryManager::SetGun(G4ITGun* pChemGun)
346 {
347     G4Scheduler::Instance()->SetGun(pChemGun);
348 }
349 
350 //------------------------------------------------------------------------------
351 
352 void G4DNAChemistryManager::Initialize()
353 {
354     //===========================================================================
355     // MT MODE
356     //===========================================================================
357     if (G4Threading::IsMultithreadedApplication())
358     {
359         //==========================================================================
360         // ON WORKER THREAD
361         //==========================================================================
362         if (G4Threading::IsWorkerThread())
363         {
364             InitializeThread(); // Will create and initialize G4Scheduler
365             return;
366         }
367         //==========================================================================
368         // ON MASTER THREAD
369         //==========================================================================
370         
371         InitializeMaster();
372         InitializeThreadSharedData();
373         return;
374     }
375     //===========================================================================
376     // IS NOT IN MT MODE
377     //===========================================================================
378     
379     InitializeMaster();
380     InitializeThreadSharedData();
381     // In this case: InitializeThread is called when Run() is called
382     return;
383 }
384 
385 //------------------------------------------------------------------------------
386 
387 void G4DNAChemistryManager::InitializeMaster()
388 {
389     if (fMasterInitialized)
390     {
391         return;
392     }
393 
394     if (fVerbose != 0)
395     {
396         G4cout << "G4DNAChemistryManager::InitializeMaster() is called" << G4endl;
397     }
398 
399 
400     if (fpUserChemistryList == nullptr)
401     {
402         G4ExceptionDescription description;
403         description << "No user chemistry list has been provided.";
404         G4Exception("G4DNAChemistryManager::InitializeMaster", "NO_CHEM_LIST",
405                     FatalException, description);
406     }else
407     {
408       fpUserChemistryList->ConstructDissociationChannels();
409       if (!fSkipReactions)
410       {
411           fpUserChemistryList->ConstructReactionTable(G4DNAMolecularReactionTable::GetReactionTable());
412       }
413       else
414       {
415           G4DNAMolecularReactionTable::GetReactionTable(); // init pointer
416       }
417     }
418 
419     G4Scheduler::Instance();
420     // creates a concrete object of the scheduler
421     fMasterInitialized = true;
422 }
423 
424 //------------------------------------------------------------------------------
425 
426 void G4DNAChemistryManager::HandleStandaloneInitialization()
427 {
428     if (!fUseInStandalone || fPhysicsTableBuilt)
429     {
430         return;
431     }
432 
433     if (fVerbose != 0)
434     {
435         G4cout << "G4DNAChemistryManager: Build the physics tables for "
436                   "molecule definition only."
437                << G4endl;
438     }
439 
440     fpUserChemistryList->BuildPhysicsTable();
441 
442     if (!fGeometryClosed)
443     {
444         if (fVerbose != 0)
445         {
446             G4cout << "G4DNAChemistryManager: Close geometry" << G4endl;
447         }
448 
449         G4GeometryManager* pGeomManager = G4GeometryManager::GetInstance();
450         pGeomManager->OpenGeometry();
451         pGeomManager->CloseGeometry(true, true);
452         fGeometryClosed = true;
453     }
454 
455     fPhysicsTableBuilt = true;
456 }
457 
458 //------------------------------------------------------------------------------
459 
460 void G4DNAChemistryManager::InitializeThread()
461 {
462     if (fpThreadData->fThreadInitialized && !fForceThreadReinitialization)
463     {
464         return;
465     }
466 
467     if (fpUserChemistryList == nullptr)
468     {
469         G4ExceptionDescription description;
470         description << "No user chemistry list has been provided.";
471         G4Exception("G4DNAChemistryManager::InitializeThread", "NO_CHEM_LIST",
472                     FatalException, description);
473     }else
474     {
475         HandleStandaloneInitialization();// To make coverty happy
476         fpUserChemistryList->ConstructTimeStepModel(G4DNAMolecularReactionTable::GetReactionTable());
477     }
478 
479     if (fVerbose != 0)
480     {
481         G4cout << "G4DNAChemistryManager::InitializeThread() is called"
482                << G4endl;
483     }
484 
485     G4Scheduler::Instance()->Initialize();
486 
487     fpThreadData->fThreadInitialized = true;
488 
489     G4VMoleculeCounter::InitializeInstance();
490 
491     InitializeFile();
492 }
493 
494 //------------------------------------------------------------------------------
495 
496 void G4DNAChemistryManager::InitializeFile()
497 {
498     if (fVerbose != 0)
499     {
500         G4cout << "G4DNAChemistryManager::InitializeFile() is called"
501                << G4endl;
502     }
503 
504     if (fpThreadData->fpPhysChemIO)
505     {
506         fpThreadData->fpPhysChemIO->InitializeFile();
507     }
508 }
509 
510 //------------------------------------------------------------------------------
511 
512 G4bool G4DNAChemistryManager::IsActivated()
513 {
514     return fgInstance != nullptr ? fgInstance->IsChemistryActivated() : false;
515 }
516 
517 //------------------------------------------------------------------------------
518 
519 G4bool G4DNAChemistryManager::IsChemistryActivated()
520 {
521     return fActiveChemistry;
522 }
523 
524 //------------------------------------------------------------------------------
525 
526 void G4DNAChemistryManager::SetChemistryActivation(G4bool flag)
527 {
528     fActiveChemistry = flag;
529 }
530 
531 //------------------------------------------------------------------------------
532 
533 void G4DNAChemistryManager::WriteInto(const G4String& output,
534                                       std::ios_base::openmode mode)
535 {
536     if (fVerbose != 0)
537     {
538         G4cout << "G4DNAChemistryManager: Write chemical stage into "
539                << output.data() << G4endl;
540     }
541 
542     if (!fpThreadData->fpPhysChemIO)
543     {
544         fpThreadData->fpPhysChemIO = std::make_unique<G4PhysChemIO::FormattedText>();
545     }
546 
547     fpThreadData->fpPhysChemIO->WriteInto(output, mode);
548 
549 }
550 
551 //------------------------------------------------------------------------------
552 
553 void G4DNAChemistryManager::AddEmptyLineInOutputFile()
554 {
555     if (fpThreadData->fpPhysChemIO)
556     {
557         fpThreadData->fpPhysChemIO->AddEmptyLineInOutputFile();
558     }
559 }
560 
561 //------------------------------------------------------------------------------
562 
563 void G4DNAChemistryManager::CloseFile()
564 {
565     if (fpThreadData->fpPhysChemIO)
566     {
567         fpThreadData->fpPhysChemIO->CloseFile();
568     }
569 }
570 
571 //------------------------------------------------------------------------------
572 
573 G4DNAWaterExcitationStructure* G4DNAChemistryManager::GetExcitationLevel()
574 {
575     if (!fpExcitationLevel)
576     {
577         fpExcitationLevel = std::make_unique<G4DNAWaterExcitationStructure>();
578     }
579     return fpExcitationLevel.get();
580 }
581 
582 //------------------------------------------------------------------------------
583 
584 G4DNAWaterIonisationStructure* G4DNAChemistryManager::GetIonisationLevel()
585 {
586     if (!fpIonisationLevel)
587     {
588         fpIonisationLevel = std::make_unique<G4DNAWaterIonisationStructure>();
589     }
590     return fpIonisationLevel.get();
591 }
592 
593 //------------------------------------------------------------------------------
594 
595 void G4DNAChemistryManager::CreateWaterMolecule(ElectronicModification modification,
596                                                 G4int electronicLevel,
597                                                 const G4Track* pIncomingTrack)
598 {
599     if (fpThreadData->fpPhysChemIO)
600     {
601         G4double energy = -1.;
602 
603         switch (modification)
604         {
605         case eDissociativeAttachment:
606             energy = 0.;
607             break;
608         case eExcitedMolecule:
609             energy = GetExcitationLevel()->ExcitationEnergy(electronicLevel);
610             break;
611         case eIonizedMolecule:
612             energy = GetIonisationLevel()->IonisationEnergy(electronicLevel);
613             break;
614         }
615 
616         fpThreadData->fpPhysChemIO->CreateWaterMolecule(modification,
617                                                         4 - electronicLevel,
618                                                         energy,
619                                                         pIncomingTrack);
620     }
621 
622     if (fActiveChemistry)
623     {
624         auto  pH2OMolecule = new G4Molecule(G4H2O::Definition());
625 
626         switch (modification)
627         {
628         case eDissociativeAttachment:
629             pH2OMolecule->AddElectron(5, 1);
630             break;
631         case eExcitedMolecule:
632             pH2OMolecule->ExciteMolecule(4 - electronicLevel);
633             break;
634         case eIonizedMolecule:
635             pH2OMolecule->IonizeMolecule(4 - electronicLevel);
636             break;
637         }
638 
639         G4double delayedTime = 0.;
640         if(pIncomingTrack->GetUserInformation() != nullptr)
641         {
642             auto pPulseInfo = dynamic_cast<G4VUserPulseInfo*>
643               (pIncomingTrack->GetUserInformation());
644             if(pPulseInfo != nullptr)
645             {
646                 delayedTime = pPulseInfo->GetDelayedTime();
647             }
648         }
649 
650         G4Track* pH2OTrack = pH2OMolecule->BuildTrack(picosecond + delayedTime,
651                                                       pIncomingTrack->GetPosition());
652 
653         pH2OTrack->SetParentID(pIncomingTrack->GetTrackID());
654         pH2OTrack->SetTrackStatus(fStopButAlive);
655         pH2OTrack->SetKineticEnergy(0.);
656         PushTrack(pH2OTrack);
657     }
658 }
659 
660 //------------------------------------------------------------------------------
661 // pFinalPosition is optional
662 void G4DNAChemistryManager::CreateSolvatedElectron(const G4Track* pIncomingTrack,
663                                                    G4ThreeVector* pFinalPosition)
664 {
665     if (fpThreadData->fpPhysChemIO)
666     {
667         fpThreadData->fpPhysChemIO->CreateSolvatedElectron(pIncomingTrack,
668                                                            pFinalPosition);
669     }
670 
671     if (fActiveChemistry)
672     {
673         G4double delayedTime = 0.;
674         if(pIncomingTrack->GetUserInformation() != nullptr)
675         {
676             auto pPulseInfo = dynamic_cast<G4VUserPulseInfo*>
677               (pIncomingTrack->GetUserInformation());
678             if(pPulseInfo != nullptr)
679             {
680                 delayedTime = pPulseInfo->GetDelayedTime();
681             }
682         }
683 
684         PushMolecule(std::make_unique<G4Molecule>(G4Electron_aq::Definition()),
685                      picosecond + delayedTime,
686                      pFinalPosition != nullptr ? *pFinalPosition : pIncomingTrack->GetPosition(),
687                      pIncomingTrack->GetTrackID());
688     }
689 }
690 
691 //------------------------------------------------------------------------------
692 
693 void G4DNAChemistryManager::PushMolecule(std::unique_ptr<G4Molecule> pMolecule,
694                                          double time,
695                                          const G4ThreeVector& position,
696                                          int parentID)
697 {
698     assert(fActiveChemistry
699            && "To inject chemical species, the chemistry must be activated. "
700               "Check chemistry activation before injecting species.");
701     G4Track* pTrack = pMolecule->BuildTrack(time, position);
702     pTrack->SetTrackStatus(fAlive);
703     pTrack->SetParentID(parentID);
704     pMolecule.release();
705     PushTrack(pTrack);
706 }
707 
708 //------------------------------------------------------------------------------
709 
710 void G4DNAChemistryManager::SetGlobalTemperature(G4double temp_K)
711 {
712     G4MolecularConfiguration::SetGlobalTemperature(temp_K);
713     G4DNAMolecularReactionTable::Instance()->ScaleReactionRateForNewTemperature(temp_K);
714 }
715 
716 //------------------------------------------------------------------------------
717 // [[deprecated]] : chemistry list should never be nullptr
718 void G4DNAChemistryManager::SetChemistryList(G4VUserChemistryList* pChemistryList)
719 {
720     fpUserChemistryList.reset(pChemistryList);
721     fOwnChemistryList = false;
722     SetChemistryActivation(true);
723 }
724 
725 void G4DNAChemistryManager::SetChemistryList(G4VUserChemistryList& chemistryList)
726 {
727     fpUserChemistryList.reset(&chemistryList);
728     fOwnChemistryList = false;
729     SetChemistryActivation(true);
730 }
731 
732 void G4DNAChemistryManager::SetChemistryList(std::unique_ptr<G4VUserChemistryList> pChemistryList)
733 {
734     fpUserChemistryList = std::move(pChemistryList);
735     fOwnChemistryList = true;
736     SetChemistryActivation(true);
737 }
738 
739 //------------------------------------------------------------------------------
740 
741 void G4DNAChemistryManager::Deregister(G4VUserChemistryList& chemistryList)
742 {
743     if (fpUserChemistryList.get() == &chemistryList)
744     {
745         if (!fpUserChemistryList->IsPhysicsConstructor() || fOwnChemistryList)
746         {
747             fpUserChemistryList.reset();
748         }
749 
750         fpUserChemistryList.release();
751     }
752 }
753 
754 //------------------------------------------------------------------------------
755 
756 void G4DNAChemistryManager::PushTrack(G4Track* pTrack)
757 {
758     G4ITTrackHolder::Instance()->Push(pTrack);
759 }
760 
761 //------------------------------------------------------------------------------
762 
763 void G4DNAChemistryManager::SetVerbose(G4int verbose)
764 {
765     fVerbose = verbose;
766 }
767 
768 //------------------------------------------------------------------------------
769 
770 G4bool G4DNAChemistryManager::IsCounterResetWhenRunEnds() const
771 {
772     return fResetCounterWhenRunEnds;
773 }
774 
775 //------------------------------------------------------------------------------
776 
777 void G4DNAChemistryManager::ResetCounterWhenRunEnds(G4bool resetCounterWhenRunEnds)
778 {
779     fResetCounterWhenRunEnds = resetCounterWhenRunEnds;
780 }
781 
782 //------------------------------------------------------------------------------
783 
784 void G4DNAChemistryManager::ForceRebuildingPhysicsTable()
785 {
786     fPhysicsTableBuilt = false;
787 }
788 
789 //------------------------------------------------------------------------------
790 
791 void G4DNAChemistryManager::ForceMasterReinitialization()
792 {
793     fMasterInitialized = false;
794     InitializeMaster();
795 }
796 
797 //------------------------------------------------------------------------------
798 
799 void G4DNAChemistryManager::ForceThreadReinitialization()
800 {
801     fForceThreadReinitialization = true;
802 }
803 
804 //------------------------------------------------------------------------------
805 
806 void G4DNAChemistryManager::TagThreadForReinitialization()
807 {
808     fpThreadData->fThreadInitialized = false;
809 }
810