ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4DNAChemistryManager.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4DNAChemistryManager.cc
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 "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"
51 #include "G4VUserChemistryList.hh"
52 #include "G4AutoLock.hh"
53 #include "G4UIcmdWithABool.hh"
56 #include "G4UIcmdWithAnInteger.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 
88 void 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))
113  , fpExcitationLevel(nullptr)
114  , fpIonisationLevel(nullptr)
115  , fpUserChemistryList(nullptr)
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  {
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  {
283  }
284  else if (pCommand == fpScaleForNewTemperature.get())
285  {
286  return fpScaleForNewTemperature->ConvertToStringWithBestUnit(G4MolecularConfiguration::GetGlobalTemperature());
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 
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 
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 {
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  }
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 
502  InitializeFile();
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 {
586  if (!fpExcitationLevel)
587  {
589  }
590  return fpExcitationLevel.get();
591 }
592 
593 //------------------------------------------------------------------------------
594 
596 {
597  if (!fpIonisationLevel)
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 
633  if (fActiveChemistry)
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 
671  if (fActiveChemistry)
672  {
673  PushMolecule(std::unique_ptr<G4Molecule>(new G4Molecule(G4Electron_aq::Definition())),
674  picosecond,
675  pFinalPosition ? *pFinalPosition : pIncomingTrack->GetPosition(),
676  pIncomingTrack->GetTrackID());
677  }
678 }
679 
680 //------------------------------------------------------------------------------
681 
682 void 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 
721 void 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 {
747  G4ITTrackHolder::Instance()->Push(pTrack);
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 }