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 // G4GeometryWorkspace - implementation << 26 // Class G4GeometryWorkspace - implementation 27 // 27 // 28 // Authors: John Apostolakis (CERN), Andrea Do << 28 // ---------------------------------------------------------------------- 29 // ------------------------------------------- << 30 29 31 #include "G4GeometryWorkspace.hh" 30 #include "G4GeometryWorkspace.hh" >> 31 >> 32 #include "G4PVReplica.hh" >> 33 #include "G4PVParameterised.hh" >> 34 #include "G4VPVParameterisation.hh" 32 #include "G4PhysicalVolumeStore.hh" 35 #include "G4PhysicalVolumeStore.hh" >> 36 #include "G4VSolid.hh" >> 37 >> 38 #include "G4LogicalVolume.hh" >> 39 #include "G4VPhysicalVolume.hh" >> 40 #include "G4PVReplica.hh" >> 41 #include "G4Region.hh" >> 42 33 #include "G4AutoLock.hh" 43 #include "G4AutoLock.hh" 34 44 35 namespace 45 namespace 36 { 46 { 37 G4Mutex mutex_init = G4MUTEX_INITIALIZER; << 47 G4Mutex solidclone = G4MUTEX_INITIALIZER; 38 G4GeometryWorkspace::pool_type thePool; 48 G4GeometryWorkspace::pool_type thePool; 39 } 49 } 40 50 41 // ------------------------------------------- 51 // ---------------------------------------------------------------------- 42 // 52 // 43 G4GeometryWorkspace::pool_type* G4GeometryWork 53 G4GeometryWorkspace::pool_type* G4GeometryWorkspace::GetPool() 44 { 54 { 45 return &thePool; 55 return &thePool; 46 } 56 } 47 57 48 // ------------------------------------------- 58 // ---------------------------------------------------------------------- 49 // 59 // 50 G4GeometryWorkspace::G4GeometryWorkspace() 60 G4GeometryWorkspace::G4GeometryWorkspace() 51 { 61 { 52 fpLogicalVolumeSIM= 62 fpLogicalVolumeSIM= 53 &const_cast<G4LVManager&>(G4LogicalVolum 63 &const_cast<G4LVManager&>(G4LogicalVolume::GetSubInstanceManager()); 54 fpPhysicalVolumeSIM= 64 fpPhysicalVolumeSIM= 55 &const_cast<G4PVManager&>( G4VPhysicalVo 65 &const_cast<G4PVManager&>( G4VPhysicalVolume::GetSubInstanceManager() ); 56 fpReplicaSIM= 66 fpReplicaSIM= 57 &const_cast<G4PVRManager&>(G4PVReplica:: 67 &const_cast<G4PVRManager&>(G4PVReplica::GetSubInstanceManager()); 58 fpRegionSIM= 68 fpRegionSIM= 59 &const_cast<G4RegionManager&>(G4Region:: 69 &const_cast<G4RegionManager&>(G4Region::GetSubInstanceManager()); 60 70 61 // Create a work area for Logical Volumes in 71 // Create a work area for Logical Volumes in this thread 62 // then capture its address 72 // then capture its address 63 // << 64 InitialiseWorkspace(); 73 InitialiseWorkspace(); 65 74 66 fLogicalVolumeOffset = fpLogicalVolumeSIM->G 75 fLogicalVolumeOffset = fpLogicalVolumeSIM->GetOffset(); 67 76 68 fPhysicalVolumeOffset = fpPhysicalVolumeSIM- 77 fPhysicalVolumeOffset = fpPhysicalVolumeSIM->GetOffset(); 69 78 70 fReplicaOffset = fpReplicaSIM->GetOffset(); 79 fReplicaOffset = fpReplicaSIM->GetOffset(); 71 80 72 fRegionOffset = fpRegionSIM->GetOffset(); 81 fRegionOffset = fpRegionSIM->GetOffset(); 73 } 82 } 74 83 75 // ------------------------------------------- 84 // ---------------------------------------------------------------------- 76 // 85 // >> 86 G4GeometryWorkspace::~G4GeometryWorkspace() >> 87 { >> 88 } >> 89 >> 90 // ---------------------------------------------------------------------- >> 91 // 77 void 92 void 78 G4GeometryWorkspace::UseWorkspace() 93 G4GeometryWorkspace::UseWorkspace() 79 { 94 { >> 95 if( fVerbose ) >> 96 { >> 97 G4cout << "G4GeometryWorkspace::UseWorkspace: Start " << G4endl; >> 98 } >> 99 >> 100 // Implementation originally in: >> 101 // G4WorkerThread::BuildGeometryAndPhysicsVector() >> 102 // and improved for G4PVParamaterised >> 103 80 // Geometry related, split classes mechanism 104 // Geometry related, split classes mechanism: instantiate sub-instance 81 // for this thread 105 // for this thread 82 // << 83 fpLogicalVolumeSIM->UseWorkArea(fLogicalVolu 106 fpLogicalVolumeSIM->UseWorkArea(fLogicalVolumeOffset); 84 fpPhysicalVolumeSIM->UseWorkArea(fPhysicalVo 107 fpPhysicalVolumeSIM->UseWorkArea(fPhysicalVolumeOffset); 85 108 86 fpReplicaSIM->UseWorkArea(fReplicaOffset); 109 fpReplicaSIM->UseWorkArea(fReplicaOffset); 87 fpRegionSIM->UseWorkArea(fRegionOffset); 110 fpRegionSIM->UseWorkArea(fRegionOffset); 88 111 89 // When recycling a workspace 112 // When recycling a workspace 90 // - it must be a lightweight operation, t 113 // - it must be a lightweight operation, to reuse a valid work area 91 // - so it must NOT Initialise anything! 114 // - so it must NOT Initialise anything! 92 // Do not call InitialisePhysicalVolumes(); 115 // Do not call InitialisePhysicalVolumes(); >> 116 >> 117 if( fVerbose ) >> 118 { >> 119 G4cout << "G4GeometryWorkspace::UseWorkspace: End " << G4endl; >> 120 } 93 } 121 } 94 122 95 // ------------------------------------------- 123 // ---------------------------------------------------------------------- 96 // 124 // 97 void G4GeometryWorkspace::ReleaseWorkspace() 125 void G4GeometryWorkspace::ReleaseWorkspace() 98 { 126 { 99 fpLogicalVolumeSIM->UseWorkArea(nullptr); << 127 fpLogicalVolumeSIM->UseWorkArea(0); 100 fpPhysicalVolumeSIM->UseWorkArea(nullptr); << 128 fpPhysicalVolumeSIM->UseWorkArea(0); 101 129 102 fpReplicaSIM->UseWorkArea(nullptr); << 130 fpReplicaSIM->UseWorkArea(0); 103 fpRegionSIM->UseWorkArea(nullptr); << 131 fpRegionSIM->UseWorkArea(0); 104 } 132 } 105 133 106 // ------------------------------------------- 134 // ---------------------------------------------------------------------- 107 // 135 // 108 void G4GeometryWorkspace::InitialisePhysicalVo 136 void G4GeometryWorkspace::InitialisePhysicalVolumes() 109 { 137 { 110 G4PhysicalVolumeStore* physVolStore = G4Phys 138 G4PhysicalVolumeStore* physVolStore = G4PhysicalVolumeStore::GetInstance(); 111 for (auto physVol : *physVolStore) << 139 for (size_t ip=0; ip<physVolStore->size(); ++ip) 112 { 140 { >> 141 G4VPhysicalVolume* physVol = (*physVolStore)[ip]; 113 G4LogicalVolume *logicalVol = physVol->Get 142 G4LogicalVolume *logicalVol = physVol->GetLogicalVolume(); 114 143 115 // Use shadow pointer 144 // Use shadow pointer 116 // 145 // 117 G4VSolid* solid = logicalVol->GetMasterSol 146 G4VSolid* solid = logicalVol->GetMasterSolid(); 118 auto g4PVReplica = dynamic_cast<G4PVReplic << 147 G4PVReplica* g4PVReplica = nullptr; >> 148 g4PVReplica = dynamic_cast<G4PVReplica*>(physVol); 119 if (g4PVReplica == nullptr) 149 if (g4PVReplica == nullptr) 120 { 150 { 121 // Placement volume 151 // Placement volume 122 // << 152 logicalVol->InitialiseWorker(logicalVol,solid,0); 123 logicalVol->InitialiseWorker(logicalVol, << 124 } 153 } 125 else 154 else 126 { 155 { 127 g4PVReplica->InitialiseWorker(g4PVReplic 156 g4PVReplica->InitialiseWorker(g4PVReplica); 128 logicalVol->InitialiseWorker(logicalVol, << 157 if( !g4PVReplica->IsParameterised() ) 129 << 158 { 130 // If the replica's solid (in LV) is cha << 159 logicalVol->InitialiseWorker(logicalVol,solid,0); 131 // it must be thread-private << 160 132 // << 161 // If the replica's solid (in LV) is changed during navigation, 133 CloneReplicaSolid( g4PVReplica ); << 162 // it must be thread-private >> 163 // >> 164 CloneReplicaSolid( g4PVReplica ); >> 165 } >> 166 else >> 167 { >> 168 G4PVParameterised *paramVol = dynamic_cast<G4PVParameterised*>(physVol); >> 169 if (paramVol == nullptr) >> 170 { >> 171 G4Exception("G4GeometryWorkspace::CreateAndUseWorkspace()", >> 172 "GeomVol0003", FatalException, >> 173 "Cannot find Parameterisation for parameterised volume."); >> 174 } >> 175 CloneParameterisedSolids( paramVol ); >> 176 } 134 } 177 } 135 } 178 } >> 179 if( fVerbose ) >> 180 { >> 181 G4cout << "G4GeometryWorkspace::InitialisePhysicalVolumes: " >> 182 << "Copying geometry - Done!" << G4endl; >> 183 } 136 } 184 } 137 185 138 // ------------------------------------------- 186 // ---------------------------------------------------------------------- 139 // Create a clone of the solid for this replic 187 // Create a clone of the solid for this replica in this thread 140 // 188 // 141 G4bool G4GeometryWorkspace::CloneReplicaSolid( << 189 G4bool G4GeometryWorkspace::CloneReplicaSolid( G4PVReplica *replicaPV ) 142 { 190 { >> 191 // The solid Ptr is in the Logical Volume >> 192 // 143 G4LogicalVolume* logicalV = replicaPV->GetLo 193 G4LogicalVolume* logicalV = replicaPV->GetLogicalVolume(); 144 G4VSolid* solid = logicalV->GetSolid(); 194 G4VSolid* solid = logicalV->GetSolid(); 145 195 146 G4AutoLock aLock(&mutex_init); << 196 G4AutoLock aLock(&solidclone); 147 G4VSolid* workerSolid = solid->Clone(); 197 G4VSolid* workerSolid = solid->Clone(); 148 aLock.unlock(); 198 aLock.unlock(); 149 199 150 if( workerSolid != nullptr ) 200 if( workerSolid != nullptr ) 151 { 201 { 152 logicalV->InitialiseWorker(logicalV,worker << 202 logicalV->InitialiseWorker(logicalV,workerSolid,0); 153 } 203 } 154 else 204 else 155 { 205 { 156 // In the case that not all solids support 206 // In the case that not all solids support(ed) the Clone() 157 // method, we do similar thing here to dyn 207 // method, we do similar thing here to dynamically cast 158 // and then get the clone method << 208 // and then get the clone method. 159 // 209 // 160 G4ExceptionDescription ed; 210 G4ExceptionDescription ed; 161 ed << "ERROR - Unable to initialise geomet 211 ed << "ERROR - Unable to initialise geometry for worker node." << "\n" 162 << "A solid lacks the Clone() method - 212 << "A solid lacks the Clone() method - or Clone() failed." << "\n" 163 << " Type of solid: " << solid->GetEn 213 << " Type of solid: " << solid->GetEntityType() << "\n" 164 << " Parameters: " << *solid; 214 << " Parameters: " << *solid; 165 G4Exception("G4GeometryWorkspace::CloneRep << 215 G4Exception("G4GeometryWorkspace::CloneParameterisedVolume()", 166 "GeomVol0003", FatalException, 216 "GeomVol0003", FatalException, ed); 167 return false; 217 return false; 168 } 218 } 169 return true; // It Worked 219 return true; // It Worked 170 } 220 } 171 221 172 // ------------------------------------------- 222 // ---------------------------------------------------------------------- >> 223 // Each G4PVParameterised instance, has associated with it at least one >> 224 // solid for each worker thread. >> 225 // *Simple* Parameterisations have a single type of solid, and the >> 226 // pointer points to the same instance of a solid during the simulation. >> 227 // For this case, it is possible to adapt automatically to >> 228 // multi-threading, simply by cloning the solid - so long >> 229 // as all solids support the Clone() method. >> 230 // >> 231 G4bool G4GeometryWorkspace:: >> 232 CloneParameterisedSolids( G4PVParameterised* paramVol ) >> 233 { >> 234 // Check whether it is a simple parameterisation or not >> 235 // >> 236 // G4VPVParameterisation *param= paramVol->GetParameterisation(); >> 237 // unsigned int numCopies= paramVol->GetMultiplicity(); >> 238 // unsigned int numDifferent= 0; >> 239 >> 240 G4LogicalVolume* logicalV= paramVol->GetLogicalVolume(); >> 241 G4VSolid* solid= logicalV->GetSolid(); >> 242 >> 243 // for( unsigned int i=0; i< numCopies; ++i) >> 244 // { >> 245 // G4VSolid *solidChk= param->ComputeSolid(i, paramVol); >> 246 // if( solidChk != solid) >> 247 // { >> 248 // ++numDifferent; >> 249 // } >> 250 // } >> 251 // if( numDifferent>0 ) >> 252 // { >> 253 // G4ExceptionDescription ed; >> 254 // ed << "ERROR - Parameterisation using several instances of Solids \n" >> 255 // << "potentially to support different types of solids. \n" >> 256 // << "Geant4-MT currently does not support this type of \n" >> 257 // << "parameterisation, sorry !"; >> 258 // G4Exception("G4GeometryWorkspace::CloneParameterisedVolume()", >> 259 // "GeomVol0001", FatalException, ed); >> 260 // } >> 261 >> 262 // Threads may attempt to clone a solids simultaneously. >> 263 // Those cloned solids will be registered into a shared solid >> 264 // store (C++ container). Need a lock to guarantee thread safety >> 265 // >> 266 G4AutoLock aLock(&solidclone); >> 267 G4VSolid *workerSolid = solid->Clone(); >> 268 aLock.unlock(); >> 269 if( workerSolid != nullptr ) >> 270 { >> 271 logicalV->InitialiseWorker(logicalV,workerSolid,0); >> 272 } >> 273 else >> 274 { >> 275 // In the case that not all solids support(ed) the Clone() >> 276 // method, we do similar thing here to dynamically cast >> 277 // and then get the clone method >> 278 // >> 279 G4ExceptionDescription ed; >> 280 ed << "ERROR - Unable to initialise geometry for worker node. \n" >> 281 << "A solid lacks the Clone() method - or Clone() failed. \n" >> 282 << " Type of solid: " << solid->GetEntityType() << "\n" >> 283 << " Parameters: " << *solid; >> 284 G4Exception("G4GeometryWorkspace::CloneParameterisedVolume()", >> 285 "GeomVol0003", FatalException, ed); >> 286 } >> 287 return true; // It Worked >> 288 } >> 289 >> 290 // ---------------------------------------------------------------------- 173 // 291 // 174 void G4GeometryWorkspace::InitialiseWorkspace( 292 void G4GeometryWorkspace::InitialiseWorkspace() 175 { 293 { >> 294 if( fVerbose ) >> 295 { >> 296 G4cout << "G4GeometryWorkspace::InitialiseWorkspace():" >> 297 << " Copying geometry - Start " << G4endl; >> 298 } >> 299 >> 300 // Implementation originally in: >> 301 // G4WorkerThread::BuildGeometryAndPhysicsVector() >> 302 // and improved for G4PVParamaterised >> 303 176 // Geometry related, split classes mechanism 304 // Geometry related, split classes mechanism: 177 // Do *NOT* instantiate sub-instance for thi 305 // Do *NOT* instantiate sub-instance for this thread, just copy the contents! 178 // 306 // 179 fpLogicalVolumeSIM->SlaveCopySubInstanceArra 307 fpLogicalVolumeSIM->SlaveCopySubInstanceArray(); 180 fpPhysicalVolumeSIM->SlaveCopySubInstanceArr 308 fpPhysicalVolumeSIM->SlaveCopySubInstanceArray(); 181 fpReplicaSIM->SlaveCopySubInstanceArray(); 309 fpReplicaSIM->SlaveCopySubInstanceArray(); 182 fpRegionSIM->SlaveInitializeSubInstance(); 310 fpRegionSIM->SlaveInitializeSubInstance(); 183 311 184 InitialisePhysicalVolumes(); 312 InitialisePhysicalVolumes(); >> 313 >> 314 if( fVerbose ) >> 315 { >> 316 G4cout << "G4GeometryWorkspace::InitialiseWorkspace: " >> 317 << "Copying geometry - Done!" << G4endl; >> 318 } 185 } 319 } 186 320 187 // ------------------------------------------- 321 // ---------------------------------------------------------------------- 188 // 322 // 189 void G4GeometryWorkspace::DestroyWorkspace() 323 void G4GeometryWorkspace::DestroyWorkspace() 190 { 324 { 191 G4PhysicalVolumeStore* physVolStore = G4Phys 325 G4PhysicalVolumeStore* physVolStore = G4PhysicalVolumeStore::GetInstance(); 192 for (auto physVol : *physVolStore) << 326 for (size_t ip=0; ip<physVolStore->size(); ++ip) 193 { 327 { >> 328 G4VPhysicalVolume* physVol = (*physVolStore)[ip]; 194 G4LogicalVolume* logicalVol = physVol->Get 329 G4LogicalVolume* logicalVol = physVol->GetLogicalVolume(); 195 auto g4PVReplica = dynamic_cast<G4PVReplic << 330 G4PVReplica* g4PVReplica = nullptr; >> 331 g4PVReplica = dynamic_cast<G4PVReplica*>(physVol); 196 if (g4PVReplica != nullptr) 332 if (g4PVReplica != nullptr) 197 { 333 { 198 g4PVReplica->TerminateWorker(g4PVReplica 334 g4PVReplica->TerminateWorker(g4PVReplica); >> 335 G4PVParameterised* paramVol = nullptr; >> 336 paramVol = dynamic_cast<G4PVParameterised*>(physVol); >> 337 if (paramVol != nullptr) >> 338 { >> 339 // G4VSolid* solid = logicalVol->fSolid; >> 340 logicalVol->TerminateWorker(logicalVol); >> 341 // if( solid->IsClone() ) delete solid; >> 342 } >> 343 else >> 344 { >> 345 logicalVol->TerminateWorker(logicalVol); >> 346 } >> 347 } >> 348 else >> 349 { >> 350 logicalVol->TerminateWorker(logicalVol); 199 } 351 } 200 logicalVol->TerminateWorker(logicalVol); << 201 } 352 } 202 << 203 // Threads may attempt to free memory simult << 204 // Need a lock to guarantee thread safety << 205 // << 206 G4AutoLock aLock(&mutex_init); << 207 fpLogicalVolumeSIM->FreeSlave(); 353 fpLogicalVolumeSIM->FreeSlave(); 208 fpPhysicalVolumeSIM->FreeSlave(); 354 fpPhysicalVolumeSIM->FreeSlave(); 209 fpReplicaSIM->FreeSlave(); 355 fpReplicaSIM->FreeSlave(); 210 fpRegionSIM->FreeSlave(); 356 fpRegionSIM->FreeSlave(); 211 aLock.unlock(); << 212 } 357 } 213 358