Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // >> 26 // $Id: G4DNAChemistryManager.cc 90900 2015-06-11 08:06:17Z gcosmo $ 26 // 27 // 27 // Author: Mathieu Karamitros (kara@cenbg.in2p 28 // Author: Mathieu Karamitros (kara@cenbg.in2p3.fr) 28 // 29 // 29 // WARNING : This class is released as a proto 30 // WARNING : This class is released as a prototype. 30 // It might strongly evolve or even disappear << 31 // It might strongly evolve or even disapear in the next releases. 31 // 32 // 32 // History: 33 // History: 33 // ----------- 34 // ----------- 34 // 10 Oct 2011 M.Karamitros created 35 // 10 Oct 2011 M.Karamitros created 35 // 36 // 36 // ------------------------------------------- 37 // ------------------------------------------------------------------- 37 38 38 #include "G4DNAChemistryManager.hh" 39 #include "G4DNAChemistryManager.hh" 39 40 40 #include "G4AutoLock.hh" << 41 #include "G4Scheduler.hh" >> 42 #include "G4SystemOfUnits.hh" >> 43 #include "G4Molecule.hh" >> 44 #include "G4VITTrackHolder.hh" >> 45 #include "G4H2O.hh" 41 #include "G4DNAMolecularReactionTable.hh" 46 #include "G4DNAMolecularReactionTable.hh" 42 #include "G4DNAWaterExcitationStructure.hh" 47 #include "G4DNAWaterExcitationStructure.hh" 43 #include "G4DNAWaterIonisationStructure.hh" 48 #include "G4DNAWaterIonisationStructure.hh" 44 #include "G4Electron_aq.hh" 49 #include "G4Electron_aq.hh" 45 #include "G4GeometryManager.hh" << 46 #include "G4H2O.hh" << 47 #include "G4MolecularConfiguration.hh" 50 #include "G4MolecularConfiguration.hh" 48 #include "G4Molecule.hh" << 51 #include "G4MoleculeCounter.hh" 49 #include "G4MoleculeFinder.hh" << 52 #include "G4VUserChemistryList.hh" 50 #include "G4MoleculeTable.hh" << 53 #include "G4AutoLock.hh" 51 #include "G4PhysChemIO.hh" << 52 #include "G4Scheduler.hh" << 53 #include "G4StateManager.hh" << 54 #include "G4SystemOfUnits.hh" << 55 #include "G4UIcmdWithABool.hh" 54 #include "G4UIcmdWithABool.hh" 56 #include "G4UIcmdWithADoubleAndUnit.hh" << 57 #include "G4UIcmdWithAnInteger.hh" << 58 #include "G4UIcmdWithoutParameter.hh" 55 #include "G4UIcmdWithoutParameter.hh" 59 #include "G4VITTrackHolder.hh" << 56 #include "G4GeometryManager.hh" 60 #include "G4VMoleculeCounter.hh" << 57 #include "G4StateManager.hh" 61 #include "G4VUserChemistryList.hh" << 58 #include "G4MoleculeFinder.hh" 62 #include "G4VUserPulseInfo.hh" << 63 << 64 #include <memory> << 65 << 66 G4DNAChemistryManager* G4DNAChemistryManager:: << 67 59 68 G4ThreadLocal G4DNAChemistryManager::ThreadLoc << 60 using namespace std; 69 G4DNAChemistryManager::fpThreadData = null << 70 61 >> 62 G4DNAChemistryManager* G4DNAChemistryManager::fgInstance; >> 63 G4ThreadLocal std::ofstream* G4DNAChemistryManager::fpgOutput_tl = 0; >> 64 G4ThreadLocal G4bool* G4DNAChemistryManager::fpgThreadInitialized_tl = 0; 71 G4Mutex chemManExistence; 65 G4Mutex chemManExistence; >> 66 //bool G4DNAChemistryManager::fActiveChemistry = false; 72 67 73 //-------------------------------------------- << 68 G4DNAChemistryManager::G4DNAChemistryManager() : 74 << 69 G4UImessenger(), G4VStateDependent() 75 G4DNAChemistryManager::ThreadLocalData::Thread << 76 { << 77 fpPhysChemIO = nullptr; << 78 fThreadInitialized = false; << 79 } << 80 << 81 //-------------------------------------------- << 82 << 83 G4DNAChemistryManager::ThreadLocalData::~Threa << 84 { << 85 fpThreadData = nullptr; << 86 } << 87 << 88 //-------------------------------------------- << 89 << 90 void G4DNAChemistryManager::SetPhysChemIO(std: << 91 { 70 { 92 fpThreadData->fpPhysChemIO = std::move(pPh << 71 //============================================================================== 93 } << 72 /* M.K: 24/11/2014 94 << 73 * To work properly, the chemistry manager should be created and initialized on 95 //-------------------------------------------- << 74 * the master thread only. If the static flag fActiveChemistry is on but the 96 << 75 * chemistry manager singleton 97 //-------------------------------------------- << 98 /* << 99 * The chemistry manager is shared between thr << 100 * It is initialized both on the master thread << 101 */ 76 */ 102 //-------------------------------------------- << 77 //============================================================================== 103 G4DNAChemistryManager::G4DNAChemistryManager() << 104 : << 105 fpChemDNADirectory(new G4UIdirectory( << 106 , fpActivateChem(new G4UIcmdWithABool( << 107 , fpRunChem(new G4UIcmdWithAnInteger(" << 108 , fpSkipReactionsFromChemList(new G4UI << 109 , fpScaleForNewTemperature(new G4UIcmd << 110 , fpInitChem(new G4UIcmdWithoutParamet << 111 , << 112 fpExcitationLevel(nullptr) << 113 , fpIonisationLevel(nullptr) << 114 , fpUserChemistryList(nullptr) << 115 { << 116 fpRunChem->SetParameterName("Number of run << 117 "(this works w << 118 fpRunChem->SetDefaultValue(1); << 119 fpScaleForNewTemperature->SetUnitCategory( << 120 } << 121 78 122 //-------------------------------------------- << 79 // if (/*fActiveChemistry &&*/ G4Threading::IsWorkerThread() >> 80 // && G4Threading::IsMultithreadedApplication()) >> 81 // { >> 82 // G4Exception("G4DNAChemistryManager::G4DNAChemistryManager", >> 83 // "G4DNAChemistryManager_MASTER_CREATION", FatalException, >> 84 // "The chemistry manager should be created and initialized on the " >> 85 // "master thread only"); >> 86 // } >> 87 >> 88 fpExcitationLevel = 0; >> 89 fpIonisationLevel = 0; >> 90 fWriteFile = false; >> 91 fpUserChemistryList = 0; >> 92 fMasterInitialized = false; >> 93 fpChemDNADirectory = new G4UIdirectory("/process/em/dna/chem/"); >> 94 fpActivateChem = new G4UIcmdWithABool("/process/em/dna/chem/activate", this); >> 95 fpRunChem = new G4UIcmdWithoutParameter("/process/em/dna/chem/run", this); >> 96 fBuildPhysicsTable = false; >> 97 fGeometryClosed = false; >> 98 fPhysicsTableBuilt = false; >> 99 fForceThreadReinitialization = false; >> 100 fFileInitialized = false; >> 101 fVerbose = 0; >> 102 fActiveChemistry = false; >> 103 } 123 104 124 G4DNAChemistryManager* G4DNAChemistryManager:: << 105 G4DNAChemistryManager* >> 106 G4DNAChemistryManager::Instance() 125 { 107 { 126 if (fgInstance == nullptr) << 108 if (fgInstance == 0) 127 { << 109 { 128 G4AutoLock lock(&chemManExistence); << 110 G4AutoLock lock(&chemManExistence); 129 if (fgInstance == nullptr) // MT : dou << 111 if (fgInstance == 0) // MT : double check at initialisation 130 { << 131 fgInstance = new G4DNAChemistryMan << 132 } << 133 lock.unlock(); << 134 } << 135 << 136 // make sure thread local data is initiali << 137 if (fpThreadData == nullptr) << 138 { 112 { 139 fpThreadData = new ThreadLocalData(); << 113 fgInstance = new G4DNAChemistryManager(); 140 } 114 } 141 << 115 lock.unlock(); 142 assert(fpThreadData != nullptr); << 116 } 143 << 117 return fgInstance; 144 return fgInstance; << 145 } 118 } 146 119 147 //-------------------------------------------- << 120 G4DNAChemistryManager* 148 << 121 G4DNAChemistryManager::GetInstanceIfExists() 149 G4DNAChemistryManager* G4DNAChemistryManager:: << 150 { 122 { 151 return fgInstance; << 123 return fgInstance; 152 } 124 } 153 125 154 //-------------------------------------------- << 155 << 156 G4DNAChemistryManager::~G4DNAChemistryManager( 126 G4DNAChemistryManager::~G4DNAChemistryManager() 157 { 127 { 158 Clear(); << 128 // G4cout << "Deleting G4DNAChemistryManager" << G4endl; 159 fgInstance = nullptr; << 129 Clear(); >> 130 fgInstance = 0; >> 131 /* >> 132 * DEBUG : check that the chemistry manager has well been deregistered >> 133 * assert(G4StateManager::GetStateManager()-> >> 134 * DeregisterDependent(this) == true); >> 135 */ 160 } 136 } 161 137 162 //-------------------------------------------- << 163 << 164 void G4DNAChemistryManager::Clear() 138 void G4DNAChemistryManager::Clear() 165 { 139 { 166 fpIonisationLevel.reset(); << 140 if (fpIonisationLevel) 167 fpExcitationLevel.reset(); << 141 { 168 << 142 delete fpIonisationLevel; 169 if (fpUserChemistryList) << 143 fpIonisationLevel = 0; 170 { << 144 171 Deregister(*fpUserChemistryList); << 145 } 172 } << 146 if (fpExcitationLevel) 173 << 147 { 174 fpChemDNADirectory.reset(); << 148 delete fpExcitationLevel; 175 fpActivateChem.reset(); << 149 fpExcitationLevel = 0; 176 fpRunChem.reset(); << 150 } 177 << 151 if (fpUserChemistryList) 178 fpSkipReactionsFromChemList.reset(); << 152 { 179 fpInitChem.reset(); << 153 if(fpUserChemistryList->IsPhysicsConstructor() == false) 180 << 154 { 181 if (fpThreadData != nullptr) << 155 delete fpUserChemistryList; 182 { << 156 } 183 delete fpThreadData; << 157 // else 184 fpThreadData = nullptr; << 158 // { 185 } << 159 // G4cout << "G4DNAChemistryManager will not delete the chemistry list " 186 << 160 // "since it inherits from G4VPhysicsConstructor and it is then " 187 G4DNAMolecularReactionTable::DeleteInstanc << 161 // "expected to be the responsability to the G4VModularPhysics to handle" 188 G4MolecularConfiguration::DeleteManager(); << 162 // " the chemistry list." << G4endl; 189 G4VMoleculeCounter::DeleteInstance(); << 163 // } >> 164 fpUserChemistryList = 0; >> 165 } >> 166 >> 167 if (fpChemDNADirectory) >> 168 { >> 169 delete fpChemDNADirectory; >> 170 fpChemDNADirectory = 0; >> 171 } >> 172 if (fpActivateChem) >> 173 { >> 174 delete fpActivateChem; >> 175 fpActivateChem = 0; >> 176 } >> 177 >> 178 if(fpRunChem) >> 179 { >> 180 delete fpRunChem; >> 181 fpRunChem = 0; >> 182 } >> 183 >> 184 G4DNAMolecularReactionTable::DeleteInstance(); >> 185 //G4MoleculeHandleManager::DeleteInstance(); >> 186 G4MolecularConfiguration::DeleteManager(); >> 187 G4MoleculeCounter::DeleteInstance(); 190 } 188 } 191 189 192 //-------------------------------------------- << 193 << 194 void G4DNAChemistryManager::DeleteInstance() 190 void G4DNAChemistryManager::DeleteInstance() 195 { 191 { 196 G4AutoLock lock(&chemManExistence); << 192 //G4cout << "G4DNAChemistryManager::DeleteInstance" << G4endl; 197 193 198 if (fgInstance != nullptr) << 194 G4AutoLock lock(&chemManExistence); 199 { << 195 200 G4DNAChemistryManager* pDeleteMe = fgI << 196 if(fgInstance) 201 fgInstance = nullptr; << 197 { 202 lock.unlock(); << 198 G4DNAChemistryManager* deleteMe = fgInstance; 203 delete pDeleteMe; << 199 fgInstance = 0; 204 } << 205 else << 206 { << 207 G4cerr << "G4DNAChemistryManager alrea << 208 } << 209 lock.unlock(); 200 lock.unlock(); >> 201 delete deleteMe; >> 202 } >> 203 else >> 204 { >> 205 G4cout << "G4DNAChemistryManager already deleted" << G4endl; >> 206 } >> 207 lock.unlock(); 210 } 208 } 211 209 212 //-------------------------------------------- << 213 << 214 G4bool G4DNAChemistryManager::Notify(G4Applica 210 G4bool G4DNAChemistryManager::Notify(G4ApplicationState requestedState) 215 { 211 { 216 if (requestedState == G4State_Quit) << 212 if (requestedState == G4State_Quit) 217 { << 213 { 218 if (fVerbose != 0) << 214 if(fVerbose) 219 { << 215 G4cout << "G4DNAChemistryManager::Notify ---> received G4State_Quit" 220 G4cout << "G4DNAChemistryManager:: << 216 << G4endl; 221 << G4endl; << 217 //DeleteInstance(); 222 } << 218 Clear(); 223 Clear(); << 219 } 224 } << 225 else if (requestedState == G4State_GeomClo << 226 { << 227 fGeometryClosed = true; << 228 } << 229 else if (requestedState == G4State_Idle) << 230 { << 231 InitializeThreadSharedData(); << 232 } << 233 << 234 return true; << 235 } << 236 220 237 //-------------------------------------------- << 221 else if(requestedState == G4State_GeomClosed) >> 222 { >> 223 fGeometryClosed = true; >> 224 } 238 225 239 void G4DNAChemistryManager::SetNewValue(G4UIco << 226 return true; 240 { << 241 if (pCommand == fpActivateChem.get()) << 242 { << 243 SetChemistryActivation(G4UIcmdWithABoo << 244 } << 245 else if (pCommand == fpRunChem.get()) << 246 { << 247 int nbExec = value.empty() ? 1 : G4UIc << 248 for (int i = 0 ; i < nbExec ; ++i) << 249 { << 250 Run(); << 251 } << 252 } << 253 else if (pCommand == fpSkipReactionsFromCh << 254 { << 255 fSkipReactions = true; << 256 } << 257 else if (pCommand == fpScaleForNewTemperat << 258 { << 259 SetGlobalTemperature(fpScaleForNewTemp << 260 } << 261 else if (pCommand == fpInitChem.get()) << 262 { << 263 Initialize(); << 264 InitializeThread(); << 265 } << 266 } 227 } 267 228 268 //-------------------------------------------- << 229 void G4DNAChemistryManager::SetNewValue(G4UIcommand* command, G4String value) 269 << 270 G4String G4DNAChemistryManager::GetCurrentValu << 271 { 230 { 272 if (pCommand == fpActivateChem.get()) << 231 if (command == fpActivateChem) 273 { << 232 { 274 return G4UIcmdWithABool::ConvertToStri << 233 Activated(G4UIcmdWithABool::GetNewBoolValue(value)); 275 } << 234 } 276 if (pCommand == fpScaleForNewTemperature.g << 235 else if (command == fpRunChem) 277 { << 236 { 278 return fpScaleForNewTemperature->Conve << 237 Run(); 279 } << 238 } 280 if (pCommand == fpSkipReactionsFromChemLis << 281 { << 282 return G4UIcmdWithABool::ConvertToStri << 283 } << 284 << 285 return ""; << 286 } 239 } 287 240 288 //-------------------------------------------- << 241 G4String G4DNAChemistryManager::GetCurrentValue(G4UIcommand* command) 289 << 290 void G4DNAChemistryManager::InitializeThreadSh << 291 { 242 { 292 if (!G4Threading::IsMasterThread()) << 243 if (command == fpActivateChem) 293 { << 244 { 294 return; << 245 return G4UIcmdWithABool::ConvertToString(fActiveChemistry); 295 } << 246 } 296 247 297 G4MoleculeTable::Instance()->PrepareMolecu << 248 return ""; 298 G4MoleculeTable::Instance()->Finalize(); << 299 } 249 } 300 250 301 //-------------------------------------------- << 302 void G4DNAChemistryManager::Run() 251 void G4DNAChemistryManager::Run() 303 { 252 { 304 if (!fActiveChemistry) << 253 if (fActiveChemistry) 305 { << 254 { 306 return; << 307 } << 308 << 309 InitializeThread(); 255 InitializeThread(); 310 256 311 if (!fMasterInitialized) << 257 if (fMasterInitialized == false) 312 { 258 { 313 G4ExceptionDescription description; << 259 G4ExceptionDescription description; 314 description << "Global components were << 260 description << "Global components were not initialized."; 315 G4Exception("G4DNAChemistryManager::Ru << 261 G4Exception("G4DNAChemistryManager::Run", "MASTER_INIT", FatalException, 316 description); << 262 description); 317 } 263 } 318 264 319 if (!fpThreadData->fThreadInitialized) << 265 if (fpgThreadInitialized_tl == 0) 320 { 266 { 321 G4ExceptionDescription description; << 267 G4ExceptionDescription description; 322 description << "Thread local component << 268 description << "Thread local components were not initialized."; 323 G4Exception("G4DNAChemistryManager::Ru << 269 G4Exception("G4DNAChemistryManager::Run", "THREAD_INIT", FatalException, 324 description); << 270 description); 325 } 271 } 326 << 272 327 G4MoleculeTable::Instance()->Finalize(); << 328 G4Scheduler::Instance()->Process(); 273 G4Scheduler::Instance()->Process(); 329 if (fResetCounterWhenRunEnds) << 330 { << 331 G4VMoleculeCounter::Instance()->ResetC << 332 } << 333 CloseFile(); 274 CloseFile(); >> 275 } 334 } 276 } 335 277 336 //-------------------------------------------- << 278 void G4DNAChemistryManager::Gun(G4ITGun* gun, bool physicsTableToBuild) 337 << 338 void G4DNAChemistryManager::UseAsStandalone(G4 << 339 { 279 { 340 fUseInStandalone = flag; << 280 fBuildPhysicsTable = physicsTableToBuild; >> 281 G4Scheduler::Instance()->SetGun(gun); 341 } 282 } 342 283 343 //-------------------------------------------- << 344 << 345 void G4DNAChemistryManager::SetGun(G4ITGun* pC << 346 { << 347 G4Scheduler::Instance()->SetGun(pChemGun); << 348 } << 349 << 350 //-------------------------------------------- << 351 << 352 void G4DNAChemistryManager::Initialize() 284 void G4DNAChemistryManager::Initialize() 353 { 285 { 354 //======================================== << 286 //=========================================================================== 355 // MT MODE << 287 // MT MODE 356 //======================================== << 288 //=========================================================================== 357 if (G4Threading::IsMultithreadedApplicatio << 289 if(G4Threading::IsMultithreadedApplication()) 358 { << 290 { 359 //==================================== << 291 //========================================================================== 360 // ON WORKER THREAD << 292 // ON WORKER THREAD 361 //==================================== << 293 //========================================================================== 362 if (G4Threading::IsWorkerThread()) << 294 if(G4Threading::IsWorkerThread()) 363 { << 295 { 364 InitializeThread(); // Will create << 296 InitializeThread(); // Will create and initialize G4ITScheduler 365 return; << 297 return; 366 } << 298 } 367 //==================================== << 299 //========================================================================== 368 // ON MASTER THREAD << 300 // ON MASTER THREAD 369 //==================================== << 301 //========================================================================== 370 << 302 else 371 InitializeMaster(); << 303 { 372 InitializeThreadSharedData(); << 304 InitializeMaster(); 373 return; << 305 return; 374 } << 306 } 375 //======================================== << 307 } 376 // IS NOT IN MT MODE << 308 //=========================================================================== 377 //======================================== << 309 // IS NOT IN MT MODE 378 << 310 //=========================================================================== >> 311 else >> 312 { 379 InitializeMaster(); 313 InitializeMaster(); 380 InitializeThreadSharedData(); << 381 // In this case: InitializeThread is calle 314 // In this case: InitializeThread is called when Run() is called 382 return; 315 return; 383 } << 316 } 384 317 385 //-------------------------------------------- << 318 } 386 319 387 void G4DNAChemistryManager::InitializeMaster() 320 void G4DNAChemistryManager::InitializeMaster() 388 { 321 { 389 if (fMasterInitialized) << 322 if (fMasterInitialized == false) >> 323 { >> 324 if(fVerbose) 390 { 325 { 391 return; << 326 G4cout << "G4DNAChemistryManager::InitializeMaster() is called" << G4endl; 392 } 327 } 393 328 394 if (fVerbose != 0) << 329 G4Scheduler::Instance(); >> 330 // creates a concrete object of the scheduler >> 331 // and track container >> 332 >> 333 if (fpUserChemistryList) 395 { 334 { 396 G4cout << "G4DNAChemistryManager::Init << 335 fpUserChemistryList->ConstructDissociationChannels(); >> 336 fpUserChemistryList->ConstructReactionTable( >> 337 G4DNAMolecularReactionTable::GetReactionTable()); >> 338 fMasterInitialized = true; 397 } 339 } 398 << 340 else 399 << 400 if (fpUserChemistryList == nullptr) << 401 { 341 { >> 342 if (fActiveChemistry) >> 343 { 402 G4ExceptionDescription description; 344 G4ExceptionDescription description; 403 description << "No user chemistry list 345 description << "No user chemistry list has been provided."; 404 G4Exception("G4DNAChemistryManager::In 346 G4Exception("G4DNAChemistryManager::InitializeMaster", "NO_CHEM_LIST", 405 FatalException, descriptio 347 FatalException, description); 406 }else << 407 { << 408 fpUserChemistryList->ConstructDissociati << 409 if (!fSkipReactions) << 410 { << 411 fpUserChemistryList->ConstructReacti << 412 } << 413 else << 414 { << 415 G4DNAMolecularReactionTable::GetReac << 416 } 348 } 417 } 349 } 418 << 350 } 419 G4Scheduler::Instance(); << 420 // creates a concrete object of the schedu << 421 fMasterInitialized = true; << 422 } 351 } 423 352 424 //-------------------------------------------- << 353 void G4DNAChemistryManager::InitializeThread() 425 << 426 void G4DNAChemistryManager::HandleStandaloneIn << 427 { 354 { 428 if (!fUseInStandalone || fPhysicsTableBuil << 355 if (fpgThreadInitialized_tl == 0 || fForceThreadReinitialization == true) 429 { << 356 { 430 return; << 357 if (fpUserChemistryList) 431 } << 432 << 433 if (fVerbose != 0) << 434 { 358 { 435 G4cout << "G4DNAChemistryManager: Buil << 359 if(fVerbose) 436 "molecule definition only." << 360 { >> 361 G4cout << "G4DNAChemistryManager::InitializeThread() is called" 437 << G4endl; 362 << G4endl; 438 } << 363 } 439 << 440 fpUserChemistryList->BuildPhysicsTable(); << 441 364 442 if (!fGeometryClosed) << 365 if (fBuildPhysicsTable && fPhysicsTableBuilt == false) 443 { << 366 { 444 if (fVerbose != 0) << 367 if(fVerbose) 445 { 368 { 446 G4cout << "G4DNAChemistryManager: << 369 G4cout << "G4DNAChemistryManager: Build the physics tables for " >> 370 "molecules." >> 371 << G4endl; 447 } 372 } 448 373 449 G4GeometryManager* pGeomManager = G4Ge << 374 fpUserChemistryList->BuildPhysicsTable(); 450 pGeomManager->OpenGeometry(); << 375 if (fGeometryClosed == false) 451 pGeomManager->CloseGeometry(true, true << 376 { 452 fGeometryClosed = true; << 377 if(fVerbose) 453 } << 378 { 454 << 379 G4cout << "G4DNAChemistryManager: Close geometry" 455 fPhysicsTableBuilt = true; << 380 << G4endl; 456 } << 381 } 457 382 458 //-------------------------------------------- << 383 G4GeometryManager* geomManager = G4GeometryManager::GetInstance(); >> 384 // G4cout << "Start closing geometry." << G4endl; >> 385 geomManager->OpenGeometry(); >> 386 geomManager->CloseGeometry(true, true); >> 387 fGeometryClosed = true; >> 388 } 459 389 460 void G4DNAChemistryManager::InitializeThread() << 390 fPhysicsTableBuilt = true; 461 { << 391 } 462 if (fpThreadData->fThreadInitialized && !f << 392 fpUserChemistryList->ConstructTimeStepModel( 463 { << 393 G4DNAMolecularReactionTable::GetReactionTable()); 464 return; << 394 G4Scheduler::Instance()->Initialize(); 465 } << 466 395 467 if (fpUserChemistryList == nullptr) << 396 fpgThreadInitialized_tl = new G4bool(true); 468 { << 469 G4ExceptionDescription description; << 470 description << "No user chemistry list << 471 G4Exception("G4DNAChemistryManager::In << 472 FatalException, descriptio << 473 }else << 474 { << 475 HandleStandaloneInitialization();// To << 476 fpUserChemistryList->ConstructTimeStep << 477 } 397 } 478 << 398 else 479 if (fVerbose != 0) << 480 { 399 { 481 G4cout << "G4DNAChemistryManager::Init << 400 G4ExceptionDescription description; 482 << G4endl; << 401 description << "No user chemistry list has been provided."; >> 402 G4Exception("G4DNAChemistryManager::InitializeThread", "NO_CHEM_LIST", >> 403 FatalException, description); 483 } 404 } 484 405 485 G4Scheduler::Instance()->Initialize(); << 406 G4MoleculeCounter::InitializeInstance(); 486 << 407 } 487 fpThreadData->fThreadInitialized = true; << 488 408 489 G4VMoleculeCounter::InitializeInstance(); << 409 InitializeFile(); 490 << 491 InitializeFile(); << 492 } 410 } 493 411 494 //-------------------------------------------- << 495 << 496 void G4DNAChemistryManager::InitializeFile() 412 void G4DNAChemistryManager::InitializeFile() 497 { 413 { 498 if (fVerbose != 0) << 414 if (fpgOutput_tl == 0 || fWriteFile == false || fFileInitialized) 499 { << 415 { 500 G4cout << "G4DNAChemistryManager::Init << 416 return; 501 << G4endl; << 417 } 502 } << 503 418 504 if (fpThreadData->fpPhysChemIO) << 419 if(fVerbose) 505 { << 420 { 506 fpThreadData->fpPhysChemIO->Initialize << 421 G4cout << "G4DNAChemistryManager::InitializeFile() is called" 507 } << 422 << G4endl; 508 } << 423 } >> 424 >> 425 *fpgOutput_tl << std::setprecision(6) << std::scientific; >> 426 *fpgOutput_tl << setw(11) << left << "#Parent ID" << setw(10) << "Molecule" >> 427 << setw(14) << "Elec Modif" << setw(13) << "Energy (eV)" >> 428 << setw(22) << "X pos of parent [nm]" << setw(22) >> 429 << "Y pos of parent [nm]" << setw(22) << "Z pos of parent [nm]" >> 430 << setw(14) << "X pos [nm]" << setw(14) << "Y pos [nm]" >> 431 << setw(14) << "Z pos [nm]" << G4endl<< setw(21) << "#" >> 432 << setw(13) << "1)io/ex=0/1" >> 433 << G4endl >> 434 << setw(21) << "#" >> 435 << setw(13) << "2)level=0...5" >> 436 << G4endl; 509 437 510 //-------------------------------------------- << 438 fFileInitialized = true; >> 439 } 511 440 512 G4bool G4DNAChemistryManager::IsActivated() 441 G4bool G4DNAChemistryManager::IsActivated() 513 { 442 { 514 return fgInstance != nullptr ? fgInstance- << 443 return Instance()->fActiveChemistry; 515 } 444 } 516 445 517 //-------------------------------------------- << 446 void G4DNAChemistryManager::Activated(G4bool flag) >> 447 { >> 448 Instance()->fActiveChemistry = flag; >> 449 } 518 450 519 G4bool G4DNAChemistryManager::IsChemistryActiv 451 G4bool G4DNAChemistryManager::IsChemistryActivated() 520 { 452 { 521 return fActiveChemistry; << 453 return fActiveChemistry; 522 } 454 } 523 455 524 //-------------------------------------------- << 525 << 526 void G4DNAChemistryManager::SetChemistryActiva 456 void G4DNAChemistryManager::SetChemistryActivation(G4bool flag) 527 { 457 { 528 fActiveChemistry = flag; << 458 fActiveChemistry = flag; 529 } 459 } 530 460 531 //-------------------------------------------- << 532 << 533 void G4DNAChemistryManager::WriteInto(const G4 461 void G4DNAChemistryManager::WriteInto(const G4String& output, 534 std::ios << 462 ios_base::openmode mode) 535 { << 536 if (fVerbose != 0) << 537 { << 538 G4cout << "G4DNAChemistryManager: Writ << 539 << output.data() << G4endl; << 540 } << 541 << 542 if (!fpThreadData->fpPhysChemIO) << 543 { << 544 fpThreadData->fpPhysChemIO = std::make << 545 } << 546 << 547 fpThreadData->fpPhysChemIO->WriteInto(outp << 548 << 549 } << 550 << 551 //-------------------------------------------- << 552 << 553 void G4DNAChemistryManager::AddEmptyLineInOutp << 554 { 463 { 555 if (fpThreadData->fpPhysChemIO) << 464 if (fVerbose) 556 { << 465 { 557 fpThreadData->fpPhysChemIO->AddEmptyLi << 466 G4cout << "G4DNAChemistryManager: Write chemical stage into " 558 } << 467 << output.data() << G4endl; >> 468 } >> 469 >> 470 fpgOutput_tl = new std::ofstream(); >> 471 fpgOutput_tl->open(output.data(), mode); >> 472 fWriteFile = true; >> 473 fFileInitialized = false; >> 474 } >> 475 >> 476 void G4DNAChemistryManager::AddEmptyLineInOuputFile() >> 477 { >> 478 if (fWriteFile) >> 479 { >> 480 *fpgOutput_tl << G4endl; >> 481 } 559 } 482 } 560 483 561 //-------------------------------------------- << 562 << 563 void G4DNAChemistryManager::CloseFile() 484 void G4DNAChemistryManager::CloseFile() 564 { 485 { 565 if (fpThreadData->fpPhysChemIO) << 486 if (fpgOutput_tl == 0) return; >> 487 >> 488 if (fpgOutput_tl->is_open()) >> 489 { >> 490 if (fVerbose) 566 { 491 { 567 fpThreadData->fpPhysChemIO->CloseFile( << 492 G4cout << "G4DNAChemistryManager: Close File" << G4endl; 568 } 493 } >> 494 fpgOutput_tl->close(); >> 495 } 569 } 496 } 570 497 571 //-------------------------------------------- << 498 G4DNAWaterExcitationStructure* 572 << 499 G4DNAChemistryManager::GetExcitationLevel() 573 G4DNAWaterExcitationStructure* G4DNAChemistryM << 574 { 500 { 575 if (!fpExcitationLevel) << 501 if (!fpExcitationLevel) 576 { << 502 { 577 fpExcitationLevel = std::make_unique<G << 503 fpExcitationLevel = new G4DNAWaterExcitationStructure; 578 } << 504 } 579 return fpExcitationLevel.get(); << 505 return fpExcitationLevel; 580 } 506 } 581 507 582 //-------------------------------------------- << 508 G4DNAWaterIonisationStructure* 583 << 509 G4DNAChemistryManager::GetIonisationLevel() 584 G4DNAWaterIonisationStructure* G4DNAChemistryM << 585 { 510 { 586 if (!fpIonisationLevel) << 511 if (!fpIonisationLevel) 587 { << 512 { 588 fpIonisationLevel = std::make_unique<G << 513 fpIonisationLevel = new G4DNAWaterIonisationStructure; 589 } << 514 } 590 return fpIonisationLevel.get(); << 515 return fpIonisationLevel; 591 } 516 } 592 517 593 //-------------------------------------------- << 594 << 595 void G4DNAChemistryManager::CreateWaterMolecul 518 void G4DNAChemistryManager::CreateWaterMolecule(ElectronicModification modification, 596 519 G4int electronicLevel, 597 << 520 const G4Track* theIncomingTrack) 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()->Exc << 610 break; << 611 case eIonizedMolecule: << 612 energy = GetIonisationLevel()->Ion << 613 break; << 614 } << 615 << 616 fpThreadData->fpPhysChemIO->CreateWate << 617 << 618 << 619 << 620 } << 621 << 622 if (fActiveChemistry) << 623 { << 624 auto pH2OMolecule = new G4Molecule(G4 << 625 << 626 switch (modification) << 627 { << 628 case eDissociativeAttachment: << 629 pH2OMolecule->AddElectron(5, 1); << 630 break; << 631 case eExcitedMolecule: << 632 pH2OMolecule->ExciteMolecule(4 - e << 633 break; << 634 case eIonizedMolecule: << 635 pH2OMolecule->IonizeMolecule(4 - e << 636 break; << 637 } << 638 << 639 G4double delayedTime = 0.; << 640 if(pIncomingTrack->GetUserInformation( << 641 { << 642 auto pPulseInfo = dynamic_cast<G4V << 643 (pIncomingTrack->GetUserInformat << 644 if(pPulseInfo != nullptr) << 645 { << 646 delayedTime = pPulseInfo->GetD << 647 } << 648 } << 649 << 650 G4Track* pH2OTrack = pH2OMolecule->Bui << 651 << 652 << 653 pH2OTrack->SetParentID(pIncomingTrack- << 654 pH2OTrack->SetTrackStatus(fStopButAliv << 655 pH2OTrack->SetKineticEnergy(0.); << 656 PushTrack(pH2OTrack); << 657 } << 658 } << 659 << 660 //-------------------------------------------- << 661 // pFinalPosition is optional << 662 void G4DNAChemistryManager::CreateSolvatedElec << 663 << 664 { 521 { 665 if (fpThreadData->fpPhysChemIO) << 522 if (fWriteFile) >> 523 { >> 524 if(!fFileInitialized) InitializeFile(); >> 525 >> 526 G4double energy = -1.; >> 527 >> 528 switch (modification) >> 529 { >> 530 case eDissociativeAttachment: >> 531 energy = 0; >> 532 break; >> 533 case eExcitedMolecule: >> 534 energy = GetExcitationLevel()->ExcitationEnergy(electronicLevel); >> 535 break; >> 536 case eIonizedMolecule: >> 537 energy = GetIonisationLevel()->IonisationEnergy(electronicLevel); >> 538 break; >> 539 } >> 540 >> 541 *fpgOutput_tl << setw(11) << left << theIncomingTrack->GetTrackID() >> 542 << setw(10) << "H2O" << left << modification << internal >> 543 << ":" << right << electronicLevel << left << setw(11) << "" >> 544 << std::setprecision(2) << std::fixed << setw(13) >> 545 << energy / eV << std::setprecision(6) << std::scientific >> 546 << setw(22) >> 547 << (theIncomingTrack->GetPosition().x()) / nanometer >> 548 << setw(22) >> 549 << (theIncomingTrack->GetPosition().y()) / nanometer >> 550 << setw(22) >> 551 << (theIncomingTrack->GetPosition().z()) / nanometer >> 552 << G4endl; >> 553 } >> 554 >> 555 if(fActiveChemistry) >> 556 { >> 557 G4Molecule * H2O = new G4Molecule (G4H2O::Definition()); >> 558 >> 559 switch (modification) >> 560 { >> 561 case eDissociativeAttachment: >> 562 H2O -> AddElectron(5,1); >> 563 break; >> 564 case eExcitedMolecule : >> 565 H2O -> ExciteMolecule(electronicLevel); >> 566 break; >> 567 case eIonizedMolecule : >> 568 H2O -> IonizeMolecule(electronicLevel); >> 569 break; >> 570 } >> 571 >> 572 G4Track * H2OTrack = H2O->BuildTrack(1*picosecond, >> 573 theIncomingTrack->GetPosition()); >> 574 >> 575 H2OTrack -> SetParentID(theIncomingTrack->GetTrackID()); >> 576 H2OTrack -> SetTrackStatus(fStopButAlive); >> 577 H2OTrack -> SetKineticEnergy(0.); >> 578 G4VITTrackHolder::Instance()->Push(H2OTrack); >> 579 } >> 580 // else >> 581 // abort(); >> 582 } >> 583 >> 584 void G4DNAChemistryManager::CreateSolvatedElectron(const G4Track* theIncomingTrack, >> 585 G4ThreeVector* finalPosition) >> 586 // finalPosition is a pointer because this argument is optional >> 587 { >> 588 if (fWriteFile) >> 589 { >> 590 if(!fFileInitialized) InitializeFile(); >> 591 >> 592 *fpgOutput_tl << setw(11) << theIncomingTrack->GetTrackID() << setw(10) >> 593 << "e_aq" << setw(14) << -1 << std::setprecision(2) >> 594 << std::fixed << setw(13) >> 595 << theIncomingTrack->GetKineticEnergy() / eV >> 596 << std::setprecision(6) << std::scientific << setw(22) >> 597 << (theIncomingTrack->GetPosition().x()) / nanometer >> 598 << setw(22) >> 599 << (theIncomingTrack->GetPosition().y()) / nanometer >> 600 << setw(22) >> 601 << (theIncomingTrack->GetPosition().z()) / nanometer; >> 602 >> 603 if (finalPosition != 0) >> 604 { >> 605 *fpgOutput_tl << setw(14) << (finalPosition->x()) / nanometer << setw(14) >> 606 << (finalPosition->y()) / nanometer << setw(14) >> 607 << (finalPosition->z()) / nanometer; >> 608 } >> 609 >> 610 *fpgOutput_tl << G4endl; >> 611 } >> 612 >> 613 if(fActiveChemistry) >> 614 { >> 615 G4Molecule* e_aq = new G4Molecule(G4Electron_aq::Definition()); >> 616 G4Track * e_aqTrack(0); >> 617 if(finalPosition) 666 { 618 { 667 fpThreadData->fpPhysChemIO->CreateSolv << 619 e_aqTrack = e_aq->BuildTrack(picosecond,*finalPosition); 668 << 669 } 620 } 670 << 621 else 671 if (fActiveChemistry) << 672 { 622 { 673 G4double delayedTime = 0.; << 623 e_aqTrack = e_aq->BuildTrack(picosecond,theIncomingTrack->GetPosition()); 674 if(pIncomingTrack->GetUserInformation( << 675 { << 676 auto pPulseInfo = dynamic_cast<G4V << 677 (pIncomingTrack->GetUserInformat << 678 if(pPulseInfo != nullptr) << 679 { << 680 delayedTime = pPulseInfo->GetD << 681 } << 682 } << 683 << 684 PushMolecule(std::make_unique<G4Molecu << 685 picosecond + delayedTime, << 686 pFinalPosition != nullptr << 687 pIncomingTrack->GetTrackI << 688 } 624 } >> 625 e_aqTrack -> SetTrackStatus(fAlive); >> 626 e_aqTrack -> SetParentID(theIncomingTrack->GetTrackID()); >> 627 G4VITTrackHolder::Instance()->Push(e_aqTrack); >> 628 } 689 } 629 } 690 630 691 //-------------------------------------------- << 631 void G4DNAChemistryManager::PushMolecule(G4Molecule*& molecule, 692 << 693 void G4DNAChemistryManager::PushMolecule(std:: << 694 doubl 632 double time, 695 const 633 const G4ThreeVector& position, 696 int p 634 int parentID) 697 { 635 { 698 assert(fActiveChemistry << 636 if (fWriteFile) 699 && "To inject chemical species, the << 637 { 700 "Check chemistry activation befo << 638 if(!fFileInitialized) InitializeFile(); 701 G4Track* pTrack = pMolecule->BuildTrack(ti << 639 702 pTrack->SetTrackStatus(fAlive); << 640 *fpgOutput_tl << setw(11) << parentID << setw(10) << molecule->GetName() 703 pTrack->SetParentID(parentID); << 641 << setw(14) << -1 << std::setprecision(2) << std::fixed 704 pMolecule.release(); << 642 << setw(13) << -1 << std::setprecision(6) << std::scientific 705 PushTrack(pTrack); << 643 << setw(22) << (position.x()) / nanometer << setw(22) 706 } << 644 << (position.y()) / nanometer << setw(22) 707 << 645 << (position.z()) / nanometer; 708 //-------------------------------------------- << 646 *fpgOutput_tl << G4endl; 709 << 647 } 710 void G4DNAChemistryManager::SetGlobalTemperatu << 648 711 { << 649 if(fActiveChemistry) 712 G4MolecularConfiguration::SetGlobalTempera << 650 { 713 G4DNAMolecularReactionTable::Instance()->S << 651 G4Track* track = molecule->BuildTrack(time,position); 714 } << 652 track -> SetTrackStatus(fAlive); 715 << 653 track -> SetParentID(parentID); 716 //-------------------------------------------- << 654 G4VITTrackHolder::Instance()->Push(track); 717 // [[deprecated]] : chemistry list should neve << 655 } 718 void G4DNAChemistryManager::SetChemistryList(G << 656 else 719 { << 657 { 720 fpUserChemistryList.reset(pChemistryList); << 658 delete molecule; 721 fOwnChemistryList = false; << 659 molecule = 0; 722 SetChemistryActivation(true); << 660 } 723 } << 661 } 724 << 662 725 void G4DNAChemistryManager::SetChemistryList(G << 663 void G4DNAChemistryManager::PushMoleculeAtParentTimeAndPlace(G4Molecule*& molecule, 726 { << 664 const G4Track* theIncomingTrack) 727 fpUserChemistryList.reset(&chemistryList); << 665 { 728 fOwnChemistryList = false; << 666 if (fWriteFile) 729 SetChemistryActivation(true); << 667 { 730 } << 668 if(!fFileInitialized) InitializeFile(); 731 << 669 732 void G4DNAChemistryManager::SetChemistryList(s << 670 *fpgOutput_tl << setw(11) << theIncomingTrack->GetTrackID() << setw(10) 733 { << 671 << molecule->GetName() << setw(14) << -1 734 fpUserChemistryList = std::move(pChemistry << 672 << std::setprecision(2) << std::fixed << setw(13) 735 fOwnChemistryList = true; << 673 << theIncomingTrack->GetKineticEnergy() / eV 736 SetChemistryActivation(true); << 674 << std::setprecision(6) << std::scientific << setw(22) 737 } << 675 << (theIncomingTrack->GetPosition().x()) / nanometer 738 << 676 << setw(22) 739 //-------------------------------------------- << 677 << (theIncomingTrack->GetPosition().y()) / nanometer 740 << 678 << setw(22) 741 void G4DNAChemistryManager::Deregister(G4VUser << 679 << (theIncomingTrack->GetPosition().z()) / nanometer; 742 { << 680 *fpgOutput_tl << G4endl; 743 if (fpUserChemistryList.get() == &chemistr << 681 } 744 { << 682 745 if (!fpUserChemistryList->IsPhysicsCon << 683 if(fActiveChemistry) 746 { << 684 { 747 fpUserChemistryList.reset(); << 685 G4Track* track = molecule->BuildTrack(theIncomingTrack->GetGlobalTime(), 748 } << 686 theIncomingTrack->GetPosition()); 749 << 687 track -> SetTrackStatus(fAlive); 750 fpUserChemistryList.release(); << 688 track -> SetParentID(theIncomingTrack->GetTrackID()); 751 } << 689 G4VITTrackHolder::Instance()->Push(track); 752 } << 690 } 753 << 691 else 754 //-------------------------------------------- << 692 { 755 << 693 delete molecule; 756 void G4DNAChemistryManager::PushTrack(G4Track* << 694 molecule = 0; 757 { << 695 } 758 G4ITTrackHolder::Instance()->Push(pTrack); << 759 } << 760 << 761 //-------------------------------------------- << 762 << 763 void G4DNAChemistryManager::SetVerbose(G4int v << 764 { << 765 fVerbose = verbose; << 766 } << 767 << 768 //-------------------------------------------- << 769 << 770 G4bool G4DNAChemistryManager::IsCounterResetWh << 771 { << 772 return fResetCounterWhenRunEnds; << 773 } << 774 << 775 //-------------------------------------------- << 776 << 777 void G4DNAChemistryManager::ResetCounterWhenRu << 778 { << 779 fResetCounterWhenRunEnds = resetCounterWhe << 780 } << 781 << 782 //-------------------------------------------- << 783 << 784 void G4DNAChemistryManager::ForceRebuildingPhy << 785 { << 786 fPhysicsTableBuilt = false; << 787 } << 788 << 789 //-------------------------------------------- << 790 << 791 void G4DNAChemistryManager::ForceMasterReiniti << 792 { << 793 fMasterInitialized = false; << 794 InitializeMaster(); << 795 } << 796 << 797 //-------------------------------------------- << 798 << 799 void G4DNAChemistryManager::ForceThreadReiniti << 800 { << 801 fForceThreadReinitialization = true; << 802 } << 803 << 804 //-------------------------------------------- << 805 << 806 void G4DNAChemistryManager::TagThreadForReinit << 807 { << 808 fpThreadData->fThreadInitialized = false; << 809 } 696 } 810 697