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