Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4DNAChemistryManager.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//
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
39
40#include "G4AutoLock.hh"
44#include "G4Electron_aq.hh"
45#include "G4GeometryManager.hh"
46#include "G4H2O.hh"
48#include "G4Molecule.hh"
50#include "G4MoleculeFinder.hh"
51#include "G4MoleculeTable.hh"
52#include "G4PhysChemIO.hh"
53#include "G4Scheduler.hh"
54#include "G4StateManager.hh"
55#include "G4SystemOfUnits.hh"
56#include "G4UIcmdWithABool.hh"
60#include "G4VITTrackHolder.hh"
61#include "G4VMoleculeCounter.hh"
63#include "G4VUserPulseInfo.hh"
64
65#include <memory>
66
67G4DNAChemistryManager* G4DNAChemistryManager::fgInstance = nullptr;
68
69G4ThreadLocal G4DNAChemistryManager::ThreadLocalData*
70 G4DNAChemistryManager::fpThreadData = nullptr;
71
73
74//------------------------------------------------------------------------------
75
76G4DNAChemistryManager::ThreadLocalData::ThreadLocalData()
77{
78 fpPhysChemIO = nullptr;
79 fThreadInitialized = false;
80}
81
82//------------------------------------------------------------------------------
83
84G4DNAChemistryManager::ThreadLocalData::~ThreadLocalData()
85{
86 fpThreadData = nullptr;
87}
88
89//------------------------------------------------------------------------------
90
91void G4DNAChemistryManager::SetPhysChemIO(std::unique_ptr<G4VPhysChemIO> pPhysChemIO)
92{
93 fpThreadData->fpPhysChemIO = std::move(pPhysChemIO);
94}
95
96//------------------------------------------------------------------------------
97
98//------------------------------------------------------------------------------
99/*
100 * The chemistry manager is shared between threads
101 * It is initialized both on the master thread and on the worker threads
102 */
103//------------------------------------------------------------------------------
105 :
106 fpChemDNADirectory(new G4UIdirectory("/chem/"))
107 , fpActivateChem(new G4UIcmdWithABool("/chem/activate", this))
108 , fpRunChem(new G4UIcmdWithAnInteger("/chem/run", this))
109 , fpSkipReactionsFromChemList(new G4UIcmdWithoutParameter("/chem/skipReactionsFromChemList", this))
110 , fpScaleForNewTemperature(new G4UIcmdWithADoubleAndUnit("/chem/temperature", this))
111 , fpInitChem(new G4UIcmdWithoutParameter("/chem/init", this))
112 ,
113 fpExcitationLevel(nullptr)
114 , fpIonisationLevel(nullptr)
115 , fpUserChemistryList(nullptr)
116{
117 fpRunChem->SetParameterName("Number of runs to execute for the chemistry module"
118 "(this works when used in standalone", true, true);
119 fpRunChem->SetDefaultValue(1);
120 fpScaleForNewTemperature->SetUnitCategory("Temperature");
121}
122
123//------------------------------------------------------------------------------
124
126{
127 if (fgInstance == nullptr)
128 {
130 if (fgInstance == nullptr) // MT : double check at initialisation
131 {
132 fgInstance = new G4DNAChemistryManager();
133 }
134 lock.unlock();
135 }
136
137 // make sure thread local data is initialized for all threads
138 if (fpThreadData == nullptr)
139 {
140 fpThreadData = new ThreadLocalData();
141 }
142
143 assert(fpThreadData != nullptr);
144
145 return fgInstance;
146}
147
148//------------------------------------------------------------------------------
149
154
155//------------------------------------------------------------------------------
156
158{
159 Clear();
160 fgInstance = nullptr;
161}
162
163//------------------------------------------------------------------------------
164
166{
167 fpIonisationLevel.reset();
168 fpExcitationLevel.reset();
169
170 if (fpUserChemistryList)
171 {
172 Deregister(*fpUserChemistryList);
173 }
174
175 fpChemDNADirectory.reset();
176 fpActivateChem.reset();
177 fpRunChem.reset();
178
179 fpSkipReactionsFromChemList.reset();
180 fpInitChem.reset();
181
182 if (fpThreadData != nullptr)
183 {
184 delete fpThreadData;
185 fpThreadData = nullptr;
186 }
187
192}
193
194//------------------------------------------------------------------------------
195
197{
199
200 if (fgInstance != nullptr)
201 {
202 G4DNAChemistryManager* pDeleteMe = fgInstance;
203 fgInstance = nullptr;
204 lock.unlock();
205 delete pDeleteMe;
206 }
207 else
208 {
209 G4cerr << "G4DNAChemistryManager already deleted" << G4endl;
210 }
211 lock.unlock();
212}
213
214//------------------------------------------------------------------------------
215
217{
218 if (requestedState == G4State_Quit)
219 {
220 if (fVerbose != 0)
221 {
222 G4cout << "G4DNAChemistryManager::Notify ---> received G4State_Quit"
223 << G4endl;
224 }
225 Clear();
226 }
227 else if (requestedState == G4State_GeomClosed)
228 {
229 fGeometryClosed = true;
230 }
231 else if (requestedState == G4State_Idle)
232 {
234 }
235
236 return true;
237}
238
239//------------------------------------------------------------------------------
240
242{
243 if (pCommand == fpActivateChem.get())
244 {
246 }
247 else if (pCommand == fpRunChem.get())
248 {
249 int nbExec = value.empty() ? 1 : G4UIcommand::ConvertToInt(value);
250 for (int i = 0 ; i < nbExec ; ++i)
251 {
252 Run();
253 }
254 }
255 else if (pCommand == fpSkipReactionsFromChemList.get())
256 {
257 fSkipReactions = true;
258 }
259 else if (pCommand == fpScaleForNewTemperature.get())
260 {
261 SetGlobalTemperature(fpScaleForNewTemperature->ConvertToDimensionedDouble(value));
262 }
263 else if (pCommand == fpInitChem.get())
264 {
265 Initialize();
267 }
268}
269
270//------------------------------------------------------------------------------
271
273{
274 if (pCommand == fpActivateChem.get())
275 {
276 return G4UIcmdWithABool::ConvertToString(fActiveChemistry);
277 }
278 if (pCommand == fpScaleForNewTemperature.get())
279 {
280 return fpScaleForNewTemperature->ConvertToStringWithBestUnit(G4MolecularConfiguration::GetGlobalTemperature());
281 }
282 if (pCommand == fpSkipReactionsFromChemList.get())
283 {
284 return G4UIcmdWithABool::ConvertToString(fSkipReactions);
285 }
286
287 return "";
288}
289
290//------------------------------------------------------------------------------
291
302
303//------------------------------------------------------------------------------
305{
306 if (!fActiveChemistry)
307 {
308 return;
309 }
310
312
313 if (!fMasterInitialized)
314 {
315 G4ExceptionDescription description;
316 description << "Global components were not initialized.";
317 G4Exception("G4DNAChemistryManager::Run", "MASTER_INIT", FatalException,
318 description);
319 }
320
321 if (!fpThreadData->fThreadInitialized)
322 {
323 G4ExceptionDescription description;
324 description << "Thread local components were not initialized.";
325 G4Exception("G4DNAChemistryManager::Run", "THREAD_INIT", FatalException,
326 description);
327 }
328
330
332
333 CloseFile();
334}
335
336//------------------------------------------------------------------------------
337
339{
340 fUseInStandalone = flag;
341}
342
343//------------------------------------------------------------------------------
344
346{
347 G4Scheduler::Instance()->SetGun(pChemGun);
348}
349
350//------------------------------------------------------------------------------
351
353{
354 //===========================================================================
355 // MT MODE
356 //===========================================================================
358 {
359 //==========================================================================
360 // ON WORKER THREAD
361 //==========================================================================
363 {
364 InitializeThread(); // Will create and initialize G4Scheduler
365 return;
366 }
367 //==========================================================================
368 // ON MASTER THREAD
369 //==========================================================================
370
373 return;
374 }
375 //===========================================================================
376 // IS NOT IN MT MODE
377 //===========================================================================
378
381 // In this case: InitializeThread is called when Run() is called
382 return;
383}
384
385//------------------------------------------------------------------------------
386
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 {
416 }
417 }
418
420 // creates a concrete object of the scheduler
421
424
425 fMasterInitialized = true;
426}
427
428//------------------------------------------------------------------------------
429
431{
432 if (!fUseInStandalone || fPhysicsTableBuilt)
433 {
434 return;
435 }
436
437 if (fVerbose != 0)
438 {
439 G4cout << "G4DNAChemistryManager: Build the physics tables for "
440 "molecule definition only."
441 << G4endl;
442 }
443
444 fpUserChemistryList->BuildPhysicsTable();
445
446 if (!fGeometryClosed)
447 {
448 if (fVerbose != 0)
449 {
450 G4cout << "G4DNAChemistryManager: Close geometry" << G4endl;
451 }
452
454 pGeomManager->OpenGeometry();
455 pGeomManager->CloseGeometry(true, true);
456 fGeometryClosed = true;
457 }
458
459 fPhysicsTableBuilt = true;
460}
461
462//------------------------------------------------------------------------------
463
465{
466 if (fpThreadData->fThreadInitialized && !fForceThreadReinitialization)
467 {
468 return;
469 }
470
471 if (fpUserChemistryList == nullptr)
472 {
473 G4ExceptionDescription description;
474 description << "No user chemistry list has been provided.";
475 G4Exception("G4DNAChemistryManager::InitializeThread", "NO_CHEM_LIST",
476 FatalException, description);
477 }else
478 {
479 HandleStandaloneInitialization();// To make coverty happy
480 fpUserChemistryList->ConstructTimeStepModel(G4DNAMolecularReactionTable::GetReactionTable());
481 }
482
483 if (fVerbose != 0)
484 {
485 G4cout << "G4DNAChemistryManager::InitializeThread() is called"
486 << G4endl;
487 }
488
490
493
494 fpThreadData->fThreadInitialized = true;
495
497}
498
499//------------------------------------------------------------------------------
500
502{
503 if (fVerbose != 0)
504 {
505 G4cout << "G4DNAChemistryManager::InitializeFile() is called"
506 << G4endl;
507 }
508
509 if (fpThreadData->fpPhysChemIO)
510 {
511 fpThreadData->fpPhysChemIO->InitializeFile();
512 }
513}
514
515//------------------------------------------------------------------------------
516
518{
519 return fgInstance != nullptr ? fgInstance->IsChemistryActivated() : false;
520}
521
522//------------------------------------------------------------------------------
523
525{
526 return fActiveChemistry;
527}
528
529//------------------------------------------------------------------------------
530
532{
533 fActiveChemistry = flag;
534}
535
536//------------------------------------------------------------------------------
537
539 std::ios_base::openmode mode)
540{
541 if (fVerbose != 0)
542 {
543 G4cout << "G4DNAChemistryManager: Write chemical stage into "
544 << output.data() << G4endl;
545 }
546
547 if (!fpThreadData->fpPhysChemIO)
548 {
549 fpThreadData->fpPhysChemIO = std::make_unique<G4PhysChemIO::FormattedText>();
550 }
551
552 fpThreadData->fpPhysChemIO->WriteInto(output, mode);
553
554}
555
556//------------------------------------------------------------------------------
557
559{
560 if (fpThreadData->fpPhysChemIO)
561 {
562 fpThreadData->fpPhysChemIO->AddEmptyLineInOutputFile();
563 }
564}
565
566//------------------------------------------------------------------------------
567
569{
570 if (fpThreadData->fpPhysChemIO)
571 {
572 fpThreadData->fpPhysChemIO->CloseFile();
573 }
574}
575
576//------------------------------------------------------------------------------
577
579{
580 if (!fpExcitationLevel)
581 {
582 fpExcitationLevel = std::make_unique<G4DNAWaterExcitationStructure>();
583 }
584 return fpExcitationLevel.get();
585}
586
587//------------------------------------------------------------------------------
588
590{
591 if (!fpIonisationLevel)
592 {
593 fpIonisationLevel = std::make_unique<G4DNAWaterIonisationStructure>();
594 }
595 return fpIonisationLevel.get();
596}
597
598//------------------------------------------------------------------------------
599
601 G4int electronicLevel,
602 const G4Track* pIncomingTrack)
603{
604 if (fpThreadData->fpPhysChemIO)
605 {
606 G4double energy = -1.;
607
608 switch (modification)
609 {
611 energy = 0.;
612 break;
613 case eExcitedMolecule:
614 energy = GetExcitationLevel()->ExcitationEnergy(electronicLevel);
615 break;
616 case eIonizedMolecule:
617 energy = GetIonisationLevel()->IonisationEnergy(electronicLevel);
618 break;
619 }
620
621 fpThreadData->fpPhysChemIO->CreateWaterMolecule(modification,
622 4 - electronicLevel,
623 energy,
624 pIncomingTrack);
625 }
626
627 if (fActiveChemistry)
628 {
629 auto pH2OMolecule = new G4Molecule(G4H2O::Definition());
630
631 switch (modification)
632 {
634 pH2OMolecule->AddElectron(5, 1);
635 break;
636 case eExcitedMolecule:
637 pH2OMolecule->ExciteMolecule(4 - electronicLevel);
638 break;
639 case eIonizedMolecule:
640 pH2OMolecule->IonizeMolecule(4 - electronicLevel);
641 break;
642 }
643
644 G4double delayedTime = 0.;
645 if(pIncomingTrack->GetUserInformation() != nullptr)
646 {
647 auto pPulseInfo = dynamic_cast<G4VUserPulseInfo*>
648 (pIncomingTrack->GetUserInformation());
649 if(pPulseInfo != nullptr)
650 {
651 delayedTime = pPulseInfo->GetDelayedTime();
652 }
653 }
654
655 G4Track *pH2OTrack = pH2OMolecule->BuildTrack(picosecond + delayedTime,
656 pIncomingTrack->GetPosition(),
657 pIncomingTrack);
658
659 pH2OTrack->SetParentID(pIncomingTrack->GetTrackID());
660 pH2OTrack->SetTrackStatus(fStopButAlive);
661 pH2OTrack->SetKineticEnergy(0.);
662 PushTrack(pH2OTrack);
663 }
664}
665
666//------------------------------------------------------------------------------
667// pFinalPosition is optional
669 G4ThreeVector* pFinalPosition)
670{
671 if (fpThreadData->fpPhysChemIO)
672 {
673 fpThreadData->fpPhysChemIO->CreateSolvatedElectron(pIncomingTrack,
674 pFinalPosition);
675 }
676
677 if (fActiveChemistry)
678 {
679 G4double delayedTime = 0.;
680 if(pIncomingTrack->GetUserInformation() != nullptr)
681 {
682 auto pPulseInfo = dynamic_cast<G4VUserPulseInfo*>
683 (pIncomingTrack->GetUserInformation());
684 if(pPulseInfo != nullptr)
685 {
686 delayedTime = pPulseInfo->GetDelayedTime();
687 }
688 }
689
690 PushMolecule(std::make_unique<G4Molecule>(G4Electron_aq::Definition()),
691 picosecond + delayedTime,
692 pFinalPosition ? *pFinalPosition : pIncomingTrack->GetPosition(),
693 pIncomingTrack->GetTrackID(),
694 pIncomingTrack);
695 }
696}
697
698//------------------------------------------------------------------------------
699
700void G4DNAChemistryManager::PushMolecule(std::unique_ptr<G4Molecule> pMolecule,
701 double time,
702 const G4ThreeVector &position,
703 int parentID,
704 const G4Track *parentTrack)
705{
706 assert(fActiveChemistry
707 && "To inject chemical species, the chemistry must be activated. "
708 "Check chemistry activation before injecting species.");
709 G4Track* pTrack = pMolecule->BuildTrack(time, position, parentTrack);
710 pTrack->SetTrackStatus(fAlive);
711 pTrack->SetParentID(parentID);
712 pMolecule.release();
713 PushTrack(pTrack);
714}
715
716//------------------------------------------------------------------------------
717
723
724//------------------------------------------------------------------------------
725// [[deprecated]] : chemistry list should never be nullptr
727{
728 fpUserChemistryList.reset(pChemistryList);
729 fOwnChemistryList = false;
731}
732
734{
735 fpUserChemistryList.reset(&chemistryList);
736 fOwnChemistryList = false;
738}
739
740void G4DNAChemistryManager::SetChemistryList(std::unique_ptr<G4VUserChemistryList> pChemistryList)
741{
742 fpUserChemistryList = std::move(pChemistryList);
743 fOwnChemistryList = true;
745}
746
747//------------------------------------------------------------------------------
748
750{
751 if (fpUserChemistryList.get() == &chemistryList)
752 {
753 if (!fpUserChemistryList->IsPhysicsConstructor() || fOwnChemistryList)
754 {
755 fpUserChemistryList.reset();
756 }
757
758 fpUserChemistryList.release();
759 }
760}
761
762//------------------------------------------------------------------------------
763
768
769//------------------------------------------------------------------------------
770
772{
773 fVerbose = verbose;
774}
775
776//------------------------------------------------------------------------------
777
782
783//------------------------------------------------------------------------------
784
789
790//------------------------------------------------------------------------------
791
796
797//------------------------------------------------------------------------------
798
799void G4DNAChemistryManager::EndOfRunAction(const G4Run* pRun) // for potential future use
800{
802}
803
804//------------------------------------------------------------------------------
805
807{
808 fPhysicsTableBuilt = false;
809}
810
811//------------------------------------------------------------------------------
812
814{
815 fMasterInitialized = false;
817}
818
819//------------------------------------------------------------------------------
820
822{
823 fForceThreadReinitialization = true;
824}
825
826//------------------------------------------------------------------------------
827
829{
830 fpThreadData->fThreadInitialized = false;
831}
G4ApplicationState
@ G4State_Idle
@ G4State_Quit
@ G4State_GeomClosed
G4TemplateAutoLock< G4Mutex > G4AutoLock
G4Mutex chemManExistence
ElectronicModification
@ eIonizedMolecule
@ eDissociativeAttachment
@ eExcitedMolecule
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
std::mutex G4Mutex
CLHEP::Hep3Vector G4ThreeVector
@ fAlive
@ fStopButAlive
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
G4GLOB_DLL std::ostream G4cerr
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
void SetPhysChemIO(std::unique_ptr< G4VPhysChemIO > pPhysChemIO)
G4String GetCurrentValue(G4UIcommand *pCommand) override
void CreateSolvatedElectron(const G4Track *, G4ThreeVector *pFinalPosition=nullptr)
void EndOfEventAction(const G4Event *)
static G4DNAChemistryManager * GetInstanceIfExists()
void BeginOfEventAction(const G4Event *)
static G4DNAChemistryManager * Instance()
void UseAsStandalone(G4bool flag)
void SetChemistryList(G4VUserChemistryList &)
void PushMolecule(std::unique_ptr< G4Molecule > pMolecule, G4double time, const G4ThreeVector &position, G4int parentID, const G4Track *parentTrack=nullptr)
void SetGlobalTemperature(G4double temperatureKelvin)
void SetGun(G4ITGun *pChemSpeciesGun)
Inject custom species to the simulation.
G4DNAWaterIonisationStructure * GetIonisationLevel()
void Deregister(G4VUserChemistryList &)
G4DNAWaterExcitationStructure * GetExcitationLevel()
void EndOfRunAction(const G4Run *)
void SetNewValue(G4UIcommand *, G4String) override
G4bool Notify(G4ApplicationState requestedState) override
void SetVerbose(G4int verbose)
void BeginOfRunAction(const G4Run *)
void WriteInto(const G4String &, std::ios_base::openmode mode=std::ios_base::out)
void CreateWaterMolecule(ElectronicModification, G4int, const G4Track *)
static G4DNAMolecularReactionTable * GetReactionTable()
static G4DNAMolecularReactionTable * Instance()
void ScaleReactionRateForNewTemperature(double temp_K)
static G4Electron_aq * Definition()
G4GeometryManager is a singleton class responsible for high level geometrical functions,...
static G4GeometryManager * GetInstance()
G4bool CloseGeometry(G4bool pOptimise=true, G4bool verbose=false, G4VPhysicalVolume *vol=nullptr)
void OpenGeometry(G4VPhysicalVolume *vol=nullptr)
static G4H2O * Definition()
Definition G4H2O.cc:42
void Push(G4Track *) override
static G4ITTrackHolder * Instance()
static void SetGlobalTemperature(G4double)
void EndOfEventAction(const G4Event *)
void BeginOfEventAction(const G4Event *)
static G4MoleculeCounterManager * GetInstanceIfExists()
static G4MoleculeCounterManager * Instance()
void Finalize(G4MoleculeDefinition *)
void PrepareMolecularConfiguration()
static G4MoleculeTable * Instance()
Definition G4Run.hh:48
void SetGun(G4ITGun *) override
static G4Scheduler * Instance()
void Process() override
void Initialize() override
void SetTrackStatus(const G4TrackStatus aTrackStatus)
G4int GetTrackID() const
const G4ThreeVector & GetPosition() const
G4VUserTrackInformation * GetUserInformation() const
void SetKineticEnergy(const G4double aValue)
void SetParentID(const G4int aValue)
static G4bool GetNewBoolValue(const char *paramString)
static G4String ConvertToString(G4bool boolVal)
static G4int ConvertToInt(const char *st)
G4bool IsWorkerThread()
G4bool IsMultithreadedApplication()
G4bool IsMasterThread()
#define G4ThreadLocal
Definition tls.hh:77