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