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 // >> 26 // >> 27 // $Id: G4GeometryWorkspace.cc 93288 2015-10-15 09:51:02Z gcosmo $ >> 28 // 25 // 29 // 26 // G4GeometryWorkspace - implementation << 30 // Class G4GeometryWorkspace - implementation 27 // 31 // 28 // Authors: John Apostolakis (CERN), Andrea Do << 32 // ---------------------------------------------------------------------- 29 // ------------------------------------------- << 30 33 31 #include "G4GeometryWorkspace.hh" 34 #include "G4GeometryWorkspace.hh" >> 35 >> 36 #include "G4PVReplica.hh" >> 37 #include "G4PVParameterised.hh" >> 38 #include "G4VPVParameterisation.hh" 32 #include "G4PhysicalVolumeStore.hh" 39 #include "G4PhysicalVolumeStore.hh" >> 40 #include "G4VSolid.hh" >> 41 >> 42 #include "G4LogicalVolume.hh" >> 43 #include "G4VPhysicalVolume.hh" >> 44 #include "G4PVReplica.hh" >> 45 #include "G4Region.hh" >> 46 33 #include "G4AutoLock.hh" 47 #include "G4AutoLock.hh" 34 48 35 namespace 49 namespace 36 { 50 { 37 G4Mutex mutex_init = G4MUTEX_INITIALIZER; << 51 G4Mutex solidclone = G4MUTEX_INITIALIZER; 38 G4GeometryWorkspace::pool_type thePool; << 39 } << 40 << 41 // ------------------------------------------- << 42 // << 43 G4GeometryWorkspace::pool_type* G4GeometryWork << 44 { << 45 return &thePool; << 46 } 52 } 47 53 48 // ------------------------------------------- 54 // ---------------------------------------------------------------------- 49 // 55 // 50 G4GeometryWorkspace::G4GeometryWorkspace() 56 G4GeometryWorkspace::G4GeometryWorkspace() >> 57 : fVerbose(false) 51 { 58 { 52 fpLogicalVolumeSIM= 59 fpLogicalVolumeSIM= 53 &const_cast<G4LVManager&>(G4LogicalVolum 60 &const_cast<G4LVManager&>(G4LogicalVolume::GetSubInstanceManager()); 54 fpPhysicalVolumeSIM= 61 fpPhysicalVolumeSIM= 55 &const_cast<G4PVManager&>( G4VPhysicalVo 62 &const_cast<G4PVManager&>( G4VPhysicalVolume::GetSubInstanceManager() ); 56 fpReplicaSIM= 63 fpReplicaSIM= 57 &const_cast<G4PVRManager&>(G4PVReplica:: 64 &const_cast<G4PVRManager&>(G4PVReplica::GetSubInstanceManager()); 58 fpRegionSIM= 65 fpRegionSIM= 59 &const_cast<G4RegionManager&>(G4Region:: 66 &const_cast<G4RegionManager&>(G4Region::GetSubInstanceManager()); 60 67 61 // Create a work area for Logical Volumes in 68 // Create a work area for Logical Volumes in this thread 62 // then capture its address 69 // then capture its address 63 // << 64 InitialiseWorkspace(); 70 InitialiseWorkspace(); 65 71 66 fLogicalVolumeOffset = fpLogicalVolumeSIM->G << 72 fLogicalVolumeOffset= fpLogicalVolumeSIM->GetOffset(); 67 73 68 fPhysicalVolumeOffset = fpPhysicalVolumeSIM- << 74 fPhysicalVolumeOffset= fpPhysicalVolumeSIM->GetOffset(); 69 75 70 fReplicaOffset = fpReplicaSIM->GetOffset(); << 76 fReplicaOffset= fpReplicaSIM->GetOffset(); 71 77 72 fRegionOffset = fpRegionSIM->GetOffset(); << 78 fRegionOffset= fpRegionSIM->GetOffset(); >> 79 } >> 80 >> 81 // ---------------------------------------------------------------------- >> 82 // >> 83 G4GeometryWorkspace::~G4GeometryWorkspace() >> 84 { 73 } 85 } 74 86 75 // ------------------------------------------- 87 // ---------------------------------------------------------------------- 76 // 88 // 77 void 89 void 78 G4GeometryWorkspace::UseWorkspace() 90 G4GeometryWorkspace::UseWorkspace() 79 { 91 { >> 92 if( fVerbose ) >> 93 { >> 94 G4cout << "G4GeometryWorkspace::UseWorkspace: Start " << G4endl; >> 95 } >> 96 >> 97 // Implementation originally in: >> 98 // G4WorkerThread::BuildGeometryAndPhysicsVector() >> 99 // and improved for G4PVParamaterised >> 100 80 // Geometry related, split classes mechanism 101 // Geometry related, split classes mechanism: instantiate sub-instance 81 // for this thread 102 // for this thread 82 // << 83 fpLogicalVolumeSIM->UseWorkArea(fLogicalVolu 103 fpLogicalVolumeSIM->UseWorkArea(fLogicalVolumeOffset); 84 fpPhysicalVolumeSIM->UseWorkArea(fPhysicalVo 104 fpPhysicalVolumeSIM->UseWorkArea(fPhysicalVolumeOffset); 85 105 86 fpReplicaSIM->UseWorkArea(fReplicaOffset); 106 fpReplicaSIM->UseWorkArea(fReplicaOffset); 87 fpRegionSIM->UseWorkArea(fRegionOffset); 107 fpRegionSIM->UseWorkArea(fRegionOffset); 88 108 89 // When recycling a workspace 109 // When recycling a workspace 90 // - it must be a lightweight operation, t 110 // - it must be a lightweight operation, to reuse a valid work area 91 // - so it must NOT Initialise anything! 111 // - so it must NOT Initialise anything! 92 // Do not call InitialisePhysicalVolumes(); 112 // Do not call InitialisePhysicalVolumes(); >> 113 >> 114 if( fVerbose ) >> 115 { >> 116 G4cout << "G4GeometryWorkspace::UseWorkspace: End " << G4endl; >> 117 } 93 } 118 } 94 119 95 // ------------------------------------------- 120 // ---------------------------------------------------------------------- 96 // 121 // 97 void G4GeometryWorkspace::ReleaseWorkspace() 122 void G4GeometryWorkspace::ReleaseWorkspace() 98 { 123 { 99 fpLogicalVolumeSIM->UseWorkArea(nullptr); << 124 fpLogicalVolumeSIM->UseWorkArea(0); 100 fpPhysicalVolumeSIM->UseWorkArea(nullptr); << 125 fpPhysicalVolumeSIM->UseWorkArea(0); 101 126 102 fpReplicaSIM->UseWorkArea(nullptr); << 127 fpReplicaSIM->UseWorkArea(0); 103 fpRegionSIM->UseWorkArea(nullptr); << 128 fpRegionSIM->UseWorkArea(0); 104 } 129 } 105 130 106 // ------------------------------------------- 131 // ---------------------------------------------------------------------- 107 // 132 // 108 void G4GeometryWorkspace::InitialisePhysicalVo 133 void G4GeometryWorkspace::InitialisePhysicalVolumes() 109 { 134 { 110 G4PhysicalVolumeStore* physVolStore = G4Phys 135 G4PhysicalVolumeStore* physVolStore = G4PhysicalVolumeStore::GetInstance(); 111 for (auto physVol : *physVolStore) << 136 for (size_t ip=0; ip<physVolStore->size(); ip++) 112 { 137 { >> 138 G4VPhysicalVolume* physVol = (*physVolStore)[ip]; 113 G4LogicalVolume *logicalVol = physVol->Get 139 G4LogicalVolume *logicalVol = physVol->GetLogicalVolume(); 114 140 115 // Use shadow pointer 141 // Use shadow pointer 116 // 142 // 117 G4VSolid* solid = logicalVol->GetMasterSol << 143 G4VSolid *solid = logicalVol->GetMasterSolid(); 118 auto g4PVReplica = dynamic_cast<G4PVReplic << 144 G4PVReplica *g4PVReplica = 0; 119 if (g4PVReplica == nullptr) << 145 g4PVReplica = dynamic_cast<G4PVReplica*>(physVol); >> 146 if (!g4PVReplica) 120 { 147 { 121 // Placement volume 148 // Placement volume 122 // << 149 logicalVol->InitialiseWorker(logicalVol,solid,0); 123 logicalVol->InitialiseWorker(logicalVol, << 124 } 150 } 125 else 151 else 126 { 152 { 127 g4PVReplica->InitialiseWorker(g4PVReplic 153 g4PVReplica->InitialiseWorker(g4PVReplica); 128 logicalVol->InitialiseWorker(logicalVol, << 154 if( ! g4PVReplica->IsParameterised() ) 129 << 155 { 130 // If the replica's solid (in LV) is cha << 156 logicalVol->InitialiseWorker(logicalVol,solid,0); 131 // it must be thread-private << 157 132 // << 158 // If the replica's solid (in LV) is changed during navigation, 133 CloneReplicaSolid( g4PVReplica ); << 159 // it must be thread-private >> 160 // >> 161 CloneReplicaSolid( g4PVReplica ); >> 162 } >> 163 else >> 164 { >> 165 G4PVParameterised *paramVol = dynamic_cast<G4PVParameterised*>(physVol); >> 166 if (!paramVol) >> 167 { >> 168 G4Exception("G4GeometryWorkspace::CreateAndUseWorkspace()", >> 169 "GeomVol0003", FatalException, >> 170 "Cannot find Parameterisation for parameterised volume."); >> 171 } >> 172 CloneParameterisedSolids( paramVol ); >> 173 } 134 } 174 } 135 } 175 } >> 176 if( fVerbose ) >> 177 { >> 178 G4cout << "G4GeometryWorkspace::InitialisePhysicalVolumes: " >> 179 << "Copying geometry - Done!" << G4endl; >> 180 } 136 } 181 } 137 182 138 // ------------------------------------------- 183 // ---------------------------------------------------------------------- 139 // Create a clone of the solid for this replic 184 // Create a clone of the solid for this replica in this thread 140 // 185 // 141 G4bool G4GeometryWorkspace::CloneReplicaSolid( << 186 G4bool G4GeometryWorkspace::CloneReplicaSolid( G4PVReplica *replicaPV ) 142 { 187 { 143 G4LogicalVolume* logicalV = replicaPV->GetLo << 188 // The solid Ptr is in the Logical Volume 144 G4VSolid* solid = logicalV->GetSolid(); << 189 // >> 190 G4LogicalVolume *logicalV= replicaPV ->GetLogicalVolume(); >> 191 G4VSolid *solid= logicalV->GetSolid(); 145 192 146 G4AutoLock aLock(&mutex_init); << 193 G4AutoLock aLock(&solidclone); 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 ) 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 solids 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(&solidclone); >> 264 G4VSolid *workerSolid = solid->Clone(); >> 265 aLock.unlock(); >> 266 if( workerSolid ) >> 267 { >> 268 logicalV->InitialiseWorker(logicalV,workerSolid,0); >> 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 >> 297 // Implementation originally in: >> 298 // G4WorkerThread::BuildGeometryAndPhysicsVector() >> 299 // and improved for G4PVParamaterised >> 300 176 // Geometry related, split classes mechanism 301 // Geometry related, split classes mechanism: 177 // Do *NOT* instantiate sub-instance for thi 302 // Do *NOT* instantiate sub-instance for this thread, just copy the contents! 178 // 303 // 179 fpLogicalVolumeSIM->SlaveCopySubInstanceArra 304 fpLogicalVolumeSIM->SlaveCopySubInstanceArray(); 180 fpPhysicalVolumeSIM->SlaveCopySubInstanceArr 305 fpPhysicalVolumeSIM->SlaveCopySubInstanceArray(); 181 fpReplicaSIM->SlaveCopySubInstanceArray(); 306 fpReplicaSIM->SlaveCopySubInstanceArray(); 182 fpRegionSIM->SlaveInitializeSubInstance(); 307 fpRegionSIM->SlaveInitializeSubInstance(); 183 308 184 InitialisePhysicalVolumes(); 309 InitialisePhysicalVolumes(); >> 310 >> 311 if( fVerbose ) >> 312 { >> 313 G4cout << "G4GeometryWorkspace::InitialiseWorkspace: " >> 314 << "Copying geometry - Done!" << G4endl; >> 315 } 185 } 316 } 186 317 187 // ------------------------------------------- 318 // ---------------------------------------------------------------------- 188 // 319 // 189 void G4GeometryWorkspace::DestroyWorkspace() 320 void G4GeometryWorkspace::DestroyWorkspace() 190 { 321 { 191 G4PhysicalVolumeStore* physVolStore = G4Phys 322 G4PhysicalVolumeStore* physVolStore = G4PhysicalVolumeStore::GetInstance(); 192 for (auto physVol : *physVolStore) << 323 for (size_t ip=0; ip<physVolStore->size(); ip++) 193 { 324 { 194 G4LogicalVolume* logicalVol = physVol->Get << 325 G4VPhysicalVolume* physVol = (*physVolStore)[ip]; 195 auto g4PVReplica = dynamic_cast<G4PVReplic << 326 G4LogicalVolume *logicalVol = physVol->GetLogicalVolume(); 196 if (g4PVReplica != nullptr) << 327 G4PVReplica *g4PVReplica = 0; >> 328 g4PVReplica = dynamic_cast<G4PVReplica*>(physVol); >> 329 if (g4PVReplica) 197 { 330 { 198 g4PVReplica->TerminateWorker(g4PVReplica 331 g4PVReplica->TerminateWorker(g4PVReplica); >> 332 G4PVParameterised *paramVol = 0; >> 333 paramVol = dynamic_cast<G4PVParameterised*>(physVol); >> 334 if (paramVol) >> 335 { >> 336 // G4VSolid *solid = logicalVol->fSolid; >> 337 logicalVol->TerminateWorker(logicalVol); >> 338 // if( solid->IsClone() ) delete solid; >> 339 } >> 340 else >> 341 { >> 342 logicalVol->TerminateWorker(logicalVol); >> 343 } >> 344 } >> 345 else >> 346 { >> 347 logicalVol->TerminateWorker(logicalVol); 199 } 348 } 200 logicalVol->TerminateWorker(logicalVol); << 201 } 349 } 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(); 350 fpLogicalVolumeSIM->FreeSlave(); 208 fpPhysicalVolumeSIM->FreeSlave(); 351 fpPhysicalVolumeSIM->FreeSlave(); 209 fpReplicaSIM->FreeSlave(); 352 fpReplicaSIM->FreeSlave(); 210 fpRegionSIM->FreeSlave(); 353 fpRegionSIM->FreeSlave(); 211 aLock.unlock(); << 212 } 354 } 213 355