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 // G4WorkerThread implementation << 27 // << 28 // Authors: X.Dong, A.Dotti, 2013 << 29 // ------------------------------------------- << 30 << 31 #include "G4WorkerThread.hh" 26 #include "G4WorkerThread.hh" 32 << 33 #include "G4GeometryWorkspace.hh" << 34 #include "G4LogicalVolume.hh" << 35 #include "G4LogicalVolumeStore.hh" << 36 #include "G4MTRunManager.hh" << 37 #include "G4ParticlesWorkspace.hh" << 38 #include "G4PhysicalVolumeStore.hh" << 39 #include "G4PhysicsListWorkspace.hh" << 40 #include "G4Region.hh" << 41 #include "G4RegionStore.hh" << 42 #include "G4SolidsWorkspace.hh" << 43 #include "G4WorkerRunManager.hh" 27 #include "G4WorkerRunManager.hh" >> 28 #include "G4MTRunManager.hh" 44 29 45 // ------------------------------------------- << 46 void G4WorkerThread::SetThreadId(G4int tid) 30 void G4WorkerThread::SetThreadId(G4int tid) 47 { 31 { 48 threadId = tid; << 32 threadId = tid; 49 } 33 } 50 34 51 // ------------------------------------------- << 52 G4int G4WorkerThread::GetThreadId() const 35 G4int G4WorkerThread::GetThreadId() const 53 { 36 { 54 return threadId; << 37 return threadId; 55 } 38 } 56 39 57 // ------------------------------------------- << 58 void G4WorkerThread::SetNumberThreads(G4int nw 40 void G4WorkerThread::SetNumberThreads(G4int nw) 59 { 41 { 60 numThreads = nw; << 42 numThreads = nw; 61 } 43 } 62 44 63 // ------------------------------------------- << 64 G4int G4WorkerThread::GetNumberThreads() const 45 G4int G4WorkerThread::GetNumberThreads() const 65 { 46 { 66 return numThreads; << 47 return numThreads; 67 } 48 } 68 49 69 // ------------------------------------------- << 50 //TODO: refactorize? Parts of these delegated to correct classes? >> 51 #include "G4LogicalVolume.hh" >> 52 #include "G4VPhysicalVolume.hh" >> 53 #include "G4PVReplica.hh" >> 54 #include "G4ParticleDefinition.hh" >> 55 #include "G4Region.hh" >> 56 #include "G4Material.hh" >> 57 #include "G4PhysicsVector.hh" >> 58 /////@@#include "G4VDecayChannel.hh" >> 59 #include "G4PhysicalVolumeStore.hh" >> 60 #include "G4LogicalVolumeStore.hh" >> 61 #include "G4MaterialTable.hh" >> 62 #include "G4PolyconeSide.hh" >> 63 #include "G4PolyhedraSide.hh" >> 64 #include "G4PVParameterised.hh" >> 65 #include "G4Threading.hh" >> 66 #include "G4AutoLock.hh" >> 67 #include "G4VUserPhysicsList.hh" >> 68 #include "G4VPhysicsConstructor.hh" >> 69 #include "G4VModularPhysicsList.hh" >> 70 #include "G4GeometryWorkspace.hh" >> 71 #include "G4GeometryWorkspacePool.hh" >> 72 #include "G4SolidsWorkspace.hh" >> 73 #include "G4SolidsWorkspacePool.hh" >> 74 >> 75 //namespace { >> 76 // G4Mutex solidclone = G4MUTEX_INITIALIZER; >> 77 //} >> 78 70 void G4WorkerThread::BuildGeometryAndPhysicsVe 79 void G4WorkerThread::BuildGeometryAndPhysicsVector() 71 { 80 { 72 // Initialise all split classes << 81 // Initialise all split classes in the geometry with copy of data from master thread 73 // with copy of data from master thread << 82 G4GeometryWorkspacePool::GetInstance()->CreateAndUseWorkspace(); 74 << 83 G4SolidsWorkspacePool::GetInstance()->CreateAndUseWorkspace(); 75 G4GeometryWorkspace::GetPool()->CreateAndUse << 84 76 G4SolidsWorkspace::GetPool()->CreateAndUseWo << 85 //Geometry related, split classes mechanism: instantiate sub-instance for this thread 77 G4ParticlesWorkspace::GetPool()->CreateAndUs << 86 //const_cast<G4LVManager&>(G4LogicalVolume::GetSubInstanceManager()).SlaveCopySubInstanceArray(); 78 G4PhysicsListWorkspace::GetPool()->CreateAnd << 87 //const_cast<G4PVManager&>(G4VPhysicalVolume::GetSubInstanceManager()).SlaveCopySubInstanceArray(); >> 88 //const_cast<G4PVRManager&>(G4PVReplica::GetSubInstanceManager()).SlaveCopySubInstanceArray(); >> 89 //const_cast<G4RegionManager&>(G4Region::GetSubInstanceManager()).SlaveInitializeSubInstance(); >> 90 //G4Material::g4materialSubInstanceManager.SlaveCopySubInstanceArray(); //< Not anymore splitted class >> 91 //const_cast<G4PlSideManager&>(G4PolyconeSide::GetSubInstanceManager()).SlaveInitializeSubInstance(); >> 92 //const_cast<G4PhSideManager&>(G4PolyhedraSide::GetSubInstanceManager()).SlaveInitializeSubInstance(); >> 93 //Physics related >> 94 //const_cast<G4PVecManager&>(G4PhysicsVector::GetSubInstanceManager()).SlaveInitializeSubInstance(); >> 95 /////@@ const_cast<G4DecayChannelManager&>(G4VDecayChannel::GetSubInstanceManager()).NewSubInstances(); >> 96 const_cast<G4PDefManager&>(G4ParticleDefinition::GetSubInstanceManager()).NewSubInstances(); >> 97 const_cast<G4VUPLManager&>(G4VUserPhysicsList::GetSubInstanceManager()).NewSubInstances(); >> 98 const_cast<G4VPCManager&>(G4VPhysicsConstructor::GetSubInstanceManager()).NewSubInstances(); >> 99 const_cast<G4VMPLManager&>(G4VModularPhysicsList::GetSubInstanceManager()).SlaveCopySubInstanceArray(); >> 100 /* >> 101 G4PhysicalVolumeStore* physVolStore = G4PhysicalVolumeStore::GetInstance(); >> 102 for (size_t ip=0; ip<physVolStore->size(); ip++) >> 103 { >> 104 G4VPhysicalVolume* physVol = (*physVolStore)[ip]; >> 105 G4LogicalVolume *g4LogicalVolume = physVol->GetLogicalVolume(); >> 106 //use shadow pointer >> 107 G4VSolid *g4VSolid = g4LogicalVolume->GetMasterSolid(); >> 108 G4PVReplica *g4PVReplica = 0; >> 109 g4PVReplica = dynamic_cast<G4PVReplica*>(physVol); >> 110 if (g4PVReplica) >> 111 { >> 112 //g4PVReplica->SlaveG4PVReplica(g4PVReplica); >> 113 g4PVReplica->InitialiseWorker(g4PVReplica); >> 114 G4PVParameterised *g4PVParameterised = 0; >> 115 g4PVParameterised = dynamic_cast<G4PVParameterised*>(physVol); >> 116 if (g4PVParameterised) >> 117 { >> 118 //01.25.2009 Xin Dong: For a G4PVParameterised instance, assoicated a >> 119 //cloned solid for each worker thread. If all solids support this clone >> 120 //method, we do not need to dynamically cast to solids that support this >> 121 //clone method. Before all solids support this clone method, we do similar >> 122 //thing here to dynamically cast and then get the clone method. >> 123 >> 124 //Threads may clone some solids simultaneously. Those cloned solids will be >> 125 //Registered into a shared solid store (C++ container). Need a lock to >> 126 //guarantee thread safety >> 127 G4AutoLock aLock(&solidclone); >> 128 G4VSolid *slaveg4VSolid = g4VSolid->Clone(); >> 129 aLock.unlock(); >> 130 //g4LogicalVolume->SlaveG4LogicalVolume(g4LogicalVolume, slaveg4VSolid, 0); >> 131 g4LogicalVolume->InitialiseWorker(g4LogicalVolume,slaveg4VSolid,0); >> 132 } >> 133 else >> 134 { >> 135 //g4LogicalVolume->SlaveG4LogicalVolume(g4LogicalVolume, g4VSolid, 0); >> 136 g4LogicalVolume->InitialiseWorker(g4LogicalVolume,g4VSolid,0); >> 137 } >> 138 } >> 139 else >> 140 { >> 141 //g4LogicalVolume->SlaveG4LogicalVolume(g4LogicalVolume, g4VSolid, 0); >> 142 g4LogicalVolume->InitialiseWorker(g4LogicalVolume,g4VSolid,0); >> 143 } >> 144 } >> 145 */ >> 146 >> 147 //const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable(); >> 148 >> 149 //size_t nmat = theMaterialTable->size(); >> 150 //size_t i; >> 151 //for(i=0; i<nmat; i++) { >> 152 // ((*theMaterialTable)[i])->SlaveG4Material(); >> 153 //} 79 } 154 } 80 155 81 // ------------------------------------------- << 82 void G4WorkerThread::DestroyGeometryAndPhysics 156 void G4WorkerThread::DestroyGeometryAndPhysicsVector() 83 { 157 { 84 // Clear all split classes << 158 #if 0 85 << 159 // Manage Geometry Workspace explicitly 86 G4GeometryWorkspace::GetPool()->CleanUpAndDe << 160 fGeometryWrk->ReleaseAndDestroyWorkspace(); 87 G4SolidsWorkspace::GetPool()->CleanUpAndDest << 161 delete fGeometryWrk; 88 G4ParticlesWorkspace::GetPool()->CleanUpAndD << 162 fGeometryWrk=0; 89 G4PhysicsListWorkspace::GetPool()->CleanUpAn << 163 #else >> 164 // Alternative: >> 165 // Initialise all split classes in the geometry with copy of data from master thread >> 166 // G4GeometryWorkspacePool::GetInstance()->ReleaseAndDestroyMyWorkspace(); >> 167 G4GeometryWorkspacePool::GetInstance()->GetWorkspace()->DestroyWorkspace(); >> 168 G4SolidsWorkspacePool::GetInstance()->GetWorkspace()->DestroyWorkspace(); >> 169 #endif >> 170 // >> 171 // >> 172 // G4PhysicalVolumeStore* physVolStore = G4PhysicalVolumeStore::GetInstance(); >> 173 // for (size_t ip=0; ip<physVolStore->size(); ip++) >> 174 // { >> 175 // G4VPhysicalVolume* physVol = (*physVolStore)[ip]; >> 176 // G4LogicalVolume *g4LogicalVolume = physVol->GetLogicalVolume(); >> 177 // // G4VSolid *g4VSolid = g4LogicalVolume->fSolid; >> 178 // G4PVReplica *g4PVReplica = 0; >> 179 // g4PVReplica = dynamic_cast<G4PVReplica*>(physVol); >> 180 // if (g4PVReplica) >> 181 // { >> 182 // //g4PVReplica->DestroySlaveG4PVReplica(g4PVReplica); >> 183 // g4PVReplica->TerminateWorker(g4PVReplica); >> 184 // G4PVParameterised *g4PVParameterised = 0; >> 185 // g4PVParameterised = dynamic_cast<G4PVParameterised*>(physVol); >> 186 // if (g4PVParameterised) >> 187 // { >> 188 // // G4VSolid *slaveg4VSolid = g4VSolid->Clone(); >> 189 // //g4LogicalVolume->DestroySlaveG4LogicalVolume(g4LogicalVolume); >> 190 // g4LogicalVolume->TerminateWorker(g4LogicalVolume); >> 191 // // delete slaveg4VSolid; >> 192 // } >> 193 // else >> 194 // { >> 195 // //g4LogicalVolume->DestroySlaveG4LogicalVolume(g4LogicalVolume); >> 196 // g4LogicalVolume->TerminateWorker(g4LogicalVolume); >> 197 // } >> 198 // } >> 199 // else >> 200 // { >> 201 // //g4LogicalVolume->DestroySlaveG4LogicalVolume(g4LogicalVolume); >> 202 // g4LogicalVolume->TerminateWorker(g4LogicalVolume); >> 203 // } >> 204 // } >> 205 // >> 206 // //const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable(); >> 207 // >> 208 // //size_t nmat = theMaterialTable->size(); >> 209 // //size_t i; >> 210 // //for(i=0; i<nmat; i++) { >> 211 // // ((*theMaterialTable)[i])->DestroySlaveG4Material(); >> 212 // //} >> 213 // >> 214 // const_cast<G4LVManager&>(G4LogicalVolume::GetSubInstanceManager()).FreeSlave(); >> 215 // const_cast<G4PVManager&>(G4VPhysicalVolume::GetSubInstanceManager()).FreeSlave(); >> 216 // const_cast<G4PVRManager&>(G4PVReplica::GetSubInstanceManager()).FreeSlave(); >> 217 // const_cast<G4PDefManager&>(G4ParticleDefinition::GetSubInstanceManager()).FreeSlave(); >> 218 // const_cast<G4RegionManager&>(G4Region::GetSubInstanceManager()).FreeSlave(); >> 219 // //const_cast<G4PVecManager&>(G4PhysicsVector::GetSubInstanceManager()).FreeSlave(); >> 220 ///////@@ const_cast<G4DecayChannelManager&>(G4VDecayChannel::GetSubInstanceManager()).FreeSlave(); >> 221 // const_cast<G4PlSideManager&>(G4PolyconeSide::GetSubInstanceManager()).FreeSlave(); >> 222 // const_cast<G4PhSideManager&>(G4PolyhedraSide::GetSubInstanceManager()).FreeSlave(); >> 223 const_cast<G4VUPLManager&>(G4VUserPhysicsList::GetSubInstanceManager()).FreeSlave(); >> 224 const_cast<G4VPCManager&>(G4VPhysicsConstructor::GetSubInstanceManager()).FreeSlave(); >> 225 const_cast<G4VMPLManager&>(G4VModularPhysicsList::GetSubInstanceManager()).FreeSlave(); 90 } 226 } 91 227 92 // ------------------------------------------- << 228 #include "G4Region.hh" >> 229 #include "G4RegionStore.hh" >> 230 93 void G4WorkerThread::UpdateGeometryAndPhysicsV 231 void G4WorkerThread::UpdateGeometryAndPhysicsVectorFromMaster() 94 { 232 { 95 // ========================================= << 233 //================================================= 96 // Step-0: keep sensitive detector and field << 234 //Step-0: keep sensitive detector and field manager 97 // ========================================= << 235 //================================================= 98 // First remember SD and Filed Associated wi << 236 // First remember SD and Filed Associated with worker 99 // in order to re-use it << 237 // in order to re-use it 100 // (note that all the stuff after this will << 238 // (note that all the stuff after this will reset SD and Field 101 using LV2SDFM = std::map<G4LogicalVolume*, s << 239 typedef std::map<G4LogicalVolume*,std::pair<G4VSensitiveDetector*,G4FieldManager*> > LV2SDFM; 102 LV2SDFM lvmap; << 240 LV2SDFM lvmap; 103 << 241 typedef std::map<G4LogicalVolume*,std::pair<G4Region*,G4bool> > LV2Region; 104 using R2FSM = std::map<G4Region*, std::pair< << 242 LV2Region lv2rmap; 105 R2FSM rgnmap; << 243 typedef std::map<G4Region*,std::pair<G4FastSimulationManager*,G4UserSteppingAction*> > R2FSM; 106 << 244 R2FSM rgnmap; 107 G4LogicalVolumeStore* mLogVolStore = G4Logic << 245 G4LogicalVolumeStore* mLogVolStore = G4LogicalVolumeStore::GetInstance(); 108 for (auto lv : *mLogVolStore) { << 246 for(size_t ip=0; ip<mLogVolStore->size(); ip++) 109 // The following needs an explanation. << 247 { 110 // Consider the case in which the user add << 248 G4LogicalVolume *lv = (*mLogVolStore)[ip]; 111 // the runs. The problem is that the threa << 249 //The following needs an explanation. 112 // of the G4LogicalVolume object is not in << 250 //Consider the case in which the user adds one LogVolume between the runs. The problem is that the thread-local part 113 // because the initialization is done once << 251 //(split class) of the G4LogicalVolume object is not initialized for workers because the initialization is done once when the 114 // (see G4MTRunManagerKernel::StartThread << 252 //thread starts (see G4MTRunManagerKernel::StartThread Step-2 that calls G4WorkerThread::BuildGeometryAndPhysicsVector in this class) 115 // G4WorkerThread::BuildGeometryAndPhysics << 253 //The problem is that pointers of SD and FM for these newly added LV 116 // The problem is that pointers of SD and << 254 //may be invalid pointers (because never initialized, we have seen this behavior in our testing). If now we remember 117 // may be invalid pointers (because never << 255 //them and re-use them in Step-4 below we set invalid pointers to LV for this thread. 118 // this behavior in our testing). If now w << 256 //Thus we need a way to know if for a given LV we need to remember or not the SD and FM pointers. 119 // them in Step-4 below we set invalid poi << 257 //To solve this problem: We assume that the ConstructSDandField is called also by Master thread 120 // Thus we need a way to know if for a giv << 258 //thus for newly added LV the shadow pointers of SD and Fields are correct. 121 // or not the SD and FM pointers. << 259 // (LIMITATION: this assumption may be too stringent, a user to save memory could instantiate SD only 122 // To solve this problem: We assume that t << 260 // for workers, but we require this not to happen!). 123 // called also by Master thread, thus for << 261 // Thus is a SD and FieldMgr are needed for this particular LV, and shadow are !=0 it means that user 124 // pointers of SD and Fields are correct. << 262 // wants an SD and FM to be associated with LV, we get the values and we remember them. 125 // (LIMITATION: this assumption may be too << 263 G4VSensitiveDetector* sd = 0; 126 // memory could instantiate SD only for wo << 264 G4FieldManager* fmgr = 0; 127 // not to happen!). << 265 if ( lv->GetMasterSensitiveDetector() != 0 ) sd = lv->GetSensitiveDetector(); 128 // Thus if a SD and FieldMgr are needed fo << 266 if ( lv->GetMasterFieldManager() != 0 ) fmgr = lv->GetFieldManager(); 129 // shadow are !=0 it means that user wants << 267 if ( sd || fmgr ) lvmap[lv] = std::make_pair(sd,fmgr); 130 // associated with LV, we get the values a << 268 G4Region* rgn = lv->GetRegion(); >> 269 G4bool isRoot = lv->IsRootRegion(); >> 270 if ( rgn || isRoot ) lv2rmap[lv] = std::make_pair(rgn,isRoot); >> 271 } >> 272 G4RegionStore* mRegStore = G4RegionStore::GetInstance(); >> 273 for(size_t ir=0; ir<mRegStore->size(); ir++) >> 274 { >> 275 G4Region* reg = (*mRegStore)[ir]; >> 276 G4FastSimulationManager* fsm = reg->GetFastSimulationManager(); >> 277 G4UserSteppingAction* usa = reg->GetRegionalSteppingAction(); >> 278 if ( reg || usa ) rgnmap[reg] = std::make_pair(fsm,usa); >> 279 } >> 280 >> 281 //=========================== >> 282 //Step-1: Clean the workspace >> 283 //=========================== >> 284 G4GeometryWorkspace* geomWorkspace= G4GeometryWorkspacePool::GetInstance()->GetWorkspace(); >> 285 geomWorkspace->DestroyWorkspace(); >> 286 G4SolidsWorkspace* solidWorkspace = G4SolidsWorkspacePool::GetInstance()->GetWorkspace(); >> 287 solidWorkspace->DestroyWorkspace(); >> 288 >> 289 //=========================== >> 290 //Step-2: Re-create and initialize workspace >> 291 //=========================== >> 292 geomWorkspace->InitialiseWorkspace(); >> 293 solidWorkspace->InitialiseWorkspace(); >> 294 >> 295 // Alternative 131 // 296 // 132 G4VSensitiveDetector* sd = nullptr; << 297 // To wipe, release and get a new one ... 133 G4FieldManager* fmgr = nullptr; << 298 // G4GeometryWorkspacePool *fWorkspaceMgr= G4GeometryWorkspaceOutlet::GetInstance(); 134 if (lv->GetMasterSensitiveDetector() != nu << 299 // fWorkspaceMgr->ReleaseAndDestroyMyWorkspace(); 135 sd = lv->GetSensitiveDetector(); << 300 // Now re-create 136 } << 301 // fWorkspaceMgr->CreateAndUseWorkspace(); 137 if (lv->GetMasterFieldManager() != nullptr << 302 138 fmgr = lv->GetFieldManager(); << 303 139 } << 304 //=================================================== 140 if (sd != nullptr || fmgr != nullptr) { << 305 //Step-4: Restore sensitive detector and field manaer 141 lvmap[lv] = std::make_pair(sd, fmgr); << 306 //=================================================== 142 } << 307 for ( LV2SDFM::const_iterator it = lvmap.begin() ; it != lvmap.end() ; ++it ) 143 } << 308 { 144 G4RegionStore* mRegStore = G4RegionStore::Ge << 309 G4LogicalVolume* lv = it->first; 145 for (auto reg : *mRegStore) { << 310 G4VSensitiveDetector* sd = (it->second).first; 146 G4FastSimulationManager* fsm = reg->GetFas << 311 G4FieldManager* fmgr = (it->second).second; 147 G4UserSteppingAction* usa = reg->GetRegion << 312 if(fmgr) lv->SetFieldManager(fmgr, false); //What should be the second parameter? We use always false for MT mode 148 if (reg != nullptr || usa != nullptr) { << 313 if(sd) lv->SetSensitiveDetector(sd); 149 rgnmap[reg] = std::make_pair(fsm, usa); << 314 } 150 } << 315 for ( LV2Region::const_iterator it2 = lv2rmap.begin() ; it2 != lv2rmap.end() ; it2++ ) 151 } << 316 { 152 << 317 G4LogicalVolume* lv2 = it2->first; 153 //=========================== << 318 G4Region* rgn = (it2->second).first; 154 // Step-1: Clean the workspace << 319 if(rgn) lv2->SetRegion(rgn); 155 //=========================== << 320 G4bool isRoot = (it2->second).second; 156 G4GeometryWorkspace* geomWorkspace = G4Geome << 321 lv2->SetRegionRootFlag(isRoot); 157 geomWorkspace->DestroyWorkspace(); << 322 } 158 G4SolidsWorkspace* solidWorkspace = G4Solids << 323 for ( R2FSM::const_iterator it3 = rgnmap.begin() ; it3 != rgnmap.end() ; it3++ ) 159 solidWorkspace->DestroyWorkspace(); << 324 { 160 << 325 G4Region* reg = it3->first; 161 //=========================== << 326 G4FastSimulationManager* fsm = (it3->second).first; 162 // Step-2: Re-create and initialize workspac << 327 if(fsm) reg->SetFastSimulationManager(fsm); 163 //=========================== << 328 G4UserSteppingAction* usa = (it3->second).second; 164 geomWorkspace->InitialiseWorkspace(); << 329 if(usa) reg->SetRegionalSteppingAction(usa); 165 solidWorkspace->InitialiseWorkspace(); << 330 } 166 << 167 //========================================== << 168 // Step-4: Restore sensitive detector and fi << 169 //========================================== << 170 for (const auto& it : lvmap) { << 171 G4LogicalVolume* lv = it.first; << 172 G4VSensitiveDetector* sd = (it.second).fir << 173 G4FieldManager* fmgr = (it.second).second; << 174 if (fmgr != nullptr) // What should be th << 175 { // We use always false for MT mode << 176 lv->SetFieldManager(fmgr, false); << 177 } << 178 if (sd != nullptr) { << 179 lv->SetSensitiveDetector(sd); << 180 } << 181 } << 182 for (const auto& it3 : rgnmap) { << 183 G4Region* reg = it3.first; << 184 G4FastSimulationManager* fsm = (it3.second << 185 if (fsm != nullptr) reg->SetFastSimulation << 186 G4UserSteppingAction* usa = (it3.second).s << 187 if (usa != nullptr) reg->SetRegionalSteppi << 188 } << 189 } << 190 << 191 // ------------------------------------------- << 192 void G4WorkerThread::SetPinAffinity(G4int affi << 193 { << 194 if (affinity == 0) return; << 195 << 196 #if !defined(WIN32) << 197 G4cout << "AFFINITY SET" << G4endl; << 198 // Assign this thread to cpus in a round rob << 199 G4int offset = affinity; << 200 G4int cpuindex = 0; << 201 if (std::abs(offset) > G4Threading::G4GetNum << 202 G4Exception("G4WorkerThread::SetPinAffinit << 203 "Cannot set thread affinity, a << 204 "number of cores"); << 205 return; << 206 } << 207 if (offset > 0) // Start assigning affinity << 208 { << 209 --offset; << 210 cpuindex = (GetThreadId() + offset) % G4Th << 211 // Round robin << 212 } << 213 else // Exclude the given CPU << 214 { << 215 offset *= -1; << 216 --offset; << 217 G4int myidx = GetThreadId() % (G4Threading << 218 cpuindex = myidx + static_cast<G4int>(myid << 219 } << 220 G4cout << "Setting affinity to:" << cpuindex << 221 << 222 # if defined(G4MULTITHREADED) << 223 // Avoid compilation warning in C90 standard << 224 G4NativeThread t = pthread_self(); << 225 # else << 226 G4NativeThread t; << 227 # endif << 228 G4bool success = G4Threading::G4SetPinAffini << 229 if (!success) { << 230 G4Exception("G4MTRunManagerKernel::StarThr << 231 "Cannot set thread affinity.") << 232 } << 233 #endif << 234 } 331 } >> 332 235 333