Geant4-11
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
65
68
70
71//------------------------------------------------------------------------------
72
74{
75 fpPhysChemIO = nullptr;
76 fThreadInitialized = false;
77}
78
79//------------------------------------------------------------------------------
80
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)
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)
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 {
140 }
141 lock.unlock();
142 }
143
144 // make sure thread local data is initialized for all threads
145 if (fpThreadData == nullptr)
146 {
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
178 {
180 }
181
182 fpChemDNADirectory.reset();
183 fpActivateChem.reset();
184 fpRunChem.reset();
185
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 {
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 {
283 }
284 else if (pCommand == fpScaleForNewTemperature.get())
285 {
287 }
288 else if (pCommand == fpSkipReactionsFromChemList.get())
289 {
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
320 {
321 G4ExceptionDescription description;
322 description << "Global components were not initialized.";
323 G4Exception("G4DNAChemistryManager::Run", "MASTER_INIT", FatalException,
324 description);
325 }
326
328 {
329 G4ExceptionDescription description;
330 description << "Thread local components were not initialized.";
331 G4Exception("G4DNAChemistryManager::Run", "THREAD_INIT", FatalException,
332 description);
333 }
334
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{
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 }
419
421 // creates a concrete object of the scheduler
422
423
424 fpUserChemistryList->ConstructDissociationChannels();
425 if (!fSkipReactions)
426 {
428 }
429 else
430 {
432 }
433 fMasterInitialized = true;
434}
435
436//------------------------------------------------------------------------------
437
439{
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{
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 }
486
487 if (fVerbose)
488 {
489 G4cout << "G4DNAChemistryManager::InitializeThread() is called"
490 << G4endl;
491 }
492
494
497
499
501
503}
504
505//------------------------------------------------------------------------------
506
508{
509 if (fVerbose)
510 {
511 G4cout << "G4DNAChemistryManager::InitializeFile() is called"
512 << G4endl;
513 }
514
516 {
517 fpThreadData->fpPhysChemIO->InitializeFile();
518 }
519}
520
521//------------------------------------------------------------------------------
522
524{
525 return fgInstance ? fgInstance->IsChemistryActivated() : false;
526}
527
528//------------------------------------------------------------------------------
529
531{
532 return fActiveChemistry;
533}
534
535//------------------------------------------------------------------------------
536
538{
539 fActiveChemistry = flag;
540}
541
542//------------------------------------------------------------------------------
543
545 std::ios_base::openmode mode)
546{
547 if (fVerbose)
548 {
549 G4cout << "G4DNAChemistryManager: Write chemical stage into "
550 << output.data() << G4endl;
551 }
552
554 {
556 }
557
558 fpThreadData->fpPhysChemIO->WriteInto(output, mode);
559
560}
561
562//------------------------------------------------------------------------------
563
565{
567 {
568 fpThreadData->fpPhysChemIO->AddEmptyLineInOutputFile();
569 }
570}
571
572//------------------------------------------------------------------------------
573
575{
577 {
578 fpThreadData->fpPhysChemIO->CloseFile();
579 }
580}
581
582//------------------------------------------------------------------------------
583
585{
587 {
589 }
590 return fpExcitationLevel.get();
591}
592
593//------------------------------------------------------------------------------
594
596{
598 {
600 }
601 return fpIonisationLevel.get();
602}
603
604//------------------------------------------------------------------------------
605
607 G4int electronicLevel,
608 const G4Track* pIncomingTrack)
609{
611 {
612 G4double energy = -1.;
613
614 switch (modification)
615 {
617 energy = 0.;
618 break;
619 case eExcitedMolecule:
620 energy = GetExcitationLevel()->ExcitationEnergy(electronicLevel);
621 break;
622 case eIonizedMolecule:
623 energy = GetIonisationLevel()->IonisationEnergy(electronicLevel);
624 break;
625 }
626
627 fpThreadData->fpPhysChemIO->CreateWaterMolecule(modification,
628 4 - electronicLevel,
629 energy,
630 pIncomingTrack);
631 }
632
634 {
635 G4Molecule* pH2OMolecule = new G4Molecule(G4H2O::Definition());
636
637 switch (modification)
638 {
640 pH2OMolecule->AddElectron(5, 1);
641 break;
642 case eExcitedMolecule:
643 pH2OMolecule->ExciteMolecule(4 - electronicLevel);
644 break;
645 case eIonizedMolecule:
646 pH2OMolecule->IonizeMolecule(4 - electronicLevel);
647 break;
648 }
649
650 G4Track* pH2OTrack = pH2OMolecule->BuildTrack(picosecond,
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
663 G4ThreeVector* pFinalPosition)
664{
666 {
667 fpThreadData->fpPhysChemIO->CreateSolvatedElectron(pIncomingTrack,
668 pFinalPosition);
669 }
670
672 {
673 PushMolecule(std::unique_ptr<G4Molecule>(new G4Molecule(G4Electron_aq::Definition())),
675 pFinalPosition ? *pFinalPosition : pIncomingTrack->GetPosition(),
676 pIncomingTrack->GetTrackID());
677 }
678}
679
680//------------------------------------------------------------------------------
681
682void G4DNAChemistryManager::PushMolecule(std::unique_ptr<G4Molecule> pMolecule,
683 double time,
684 const G4ThreeVector& position,
685 int parentID)
686{
687 assert(fActiveChemistry
688 && "To inject chemical species, the chemistry must be activated. "
689 "Check chemistry activation before injecting species.");
690 G4Track* pTrack = pMolecule->BuildTrack(time, position);
691 pTrack->SetTrackStatus(fAlive);
692 pTrack->SetParentID(parentID);
693 pMolecule.release();
694 PushTrack(pTrack);
695}
696
697//------------------------------------------------------------------------------
698
700{
703}
704
705//------------------------------------------------------------------------------
706// [[deprecated]] : chemistry list should never be nullptr
708{
709 fpUserChemistryList.reset(pChemistryList);
710 fOwnChemistryList = false;
712}
713
715{
716 fpUserChemistryList.reset(&chemistryList);
717 fOwnChemistryList = false;
719}
720
721void G4DNAChemistryManager::SetChemistryList(std::unique_ptr<G4VUserChemistryList> pChemistryList)
722{
723 fpUserChemistryList = std::move(pChemistryList);
724 fOwnChemistryList = true;
726}
727
728//------------------------------------------------------------------------------
729
731{
732 if (fpUserChemistryList.get() == &chemistryList)
733 {
734 if (!fpUserChemistryList->IsPhysicsConstructor() || fOwnChemistryList)
735 {
736 fpUserChemistryList.reset();
737 }
738
739 fpUserChemistryList.release();
740 }
741}
742
743//------------------------------------------------------------------------------
744
746{
748}
749
750//------------------------------------------------------------------------------
751
753{
754 fVerbose = verbose;
755}
756
757//------------------------------------------------------------------------------
758
760{
762}
763
764//------------------------------------------------------------------------------
765
767{
768 fResetCounterWhenRunEnds = resetCounterWhenRunEnds;
769}
770
771//------------------------------------------------------------------------------
772
774{
775 fPhysicsTableBuilt = false;
776}
777
778//------------------------------------------------------------------------------
779
781{
782 fMasterInitialized = false;
784}
785
786//------------------------------------------------------------------------------
787
789{
791}
792
793//------------------------------------------------------------------------------
794
796{
798}
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:35
std::ostringstream G4ExceptionDescription
Definition: G4Exception.hh:40
static constexpr double picosecond
Definition: G4SIunits.hh:141
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)
std::unique_ptr< G4UIcmdWithABool > fpActivateChem
std::unique_ptr< G4DNAWaterIonisationStructure > fpIonisationLevel
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)
static G4ThreadLocal ThreadLocalData * fpThreadData
std::unique_ptr< G4UIcmdWithoutParameter > fpInitChem
void ResetCounterWhenRunEnds(G4bool resetCounterWhenRunEnds)
void SetGlobalTemperature(G4double temperatureKelvin)
void SetGun(G4ITGun *pChemSpeciesGun)
Inject custom species to the simulation.
G4DNAWaterIonisationStructure * GetIonisationLevel()
void Deregister(G4VUserChemistryList &)
std::unique_ptr< G4UIcmdWithADoubleAndUnit > fpScaleForNewTemperature
std::unique_ptr< G4UIdirectory > fpChemDNADirectory
G4DNAWaterExcitationStructure * GetExcitationLevel()
void SetNewValue(G4UIcommand *, G4String) override
std::unique_ptr< G4VUserChemistryList > fpUserChemistryList
std::unique_ptr< G4DNAWaterExcitationStructure > fpExcitationLevel
G4bool Notify(G4ApplicationState requestedState) override
std::unique_ptr< G4UIcmdWithoutParameter > fpSkipReactionsFromChemList
void SetVerbose(G4int verbose)
std::unique_ptr< G4UIcmdWithAnInteger > fpRunChem
static G4DNAChemistryManager * fgInstance
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:308
void AddElectron(G4int orbit, G4int n=1)
Definition: G4Molecule.cc:315
G4Track * BuildTrack(G4double globalTime, const G4ThreeVector &Position)
Definition: G4Molecule.cc:373
void ExciteMolecule(G4int)
Definition: G4Molecule.cc:301
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:445
static G4int ConvertToInt(const char *st)
Definition: G4UIcommand.cc:557
static void InitializeInstance()
static void DeleteInstance()
static G4VMoleculeCounter * Instance()
virtual void ResetCounter()=0
G4double energy(const ThreeVector &p, const G4double m)
G4bool IsWorkerThread()
Definition: G4Threading.cc:123
G4bool IsMultithreadedApplication()
Definition: G4Threading.cc:130
G4bool IsMasterThread()
Definition: G4Threading.cc:124
std::unique_ptr< G4VPhysChemIO > fpPhysChemIO
#define G4ThreadLocal
Definition: tls.hh:77