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 #include "G4PhysicalVolumeStore.hh" 32 #include "G4PhysicalVolumeStore.hh" 33 #include "G4AutoLock.hh" 33 #include "G4AutoLock.hh" 34 34 35 namespace 35 namespace 36 { 36 { 37 G4Mutex mutex_init = G4MUTEX_INITIALIZER; 37 G4Mutex mutex_init = G4MUTEX_INITIALIZER; 38 G4GeometryWorkspace::pool_type thePool; 38 G4GeometryWorkspace::pool_type thePool; 39 } 39 } 40 40 41 // ------------------------------------------- 41 // ---------------------------------------------------------------------- 42 // 42 // 43 G4GeometryWorkspace::pool_type* G4GeometryWork 43 G4GeometryWorkspace::pool_type* G4GeometryWorkspace::GetPool() 44 { 44 { 45 return &thePool; 45 return &thePool; 46 } 46 } 47 47 48 // ------------------------------------------- 48 // ---------------------------------------------------------------------- 49 // 49 // 50 G4GeometryWorkspace::G4GeometryWorkspace() 50 G4GeometryWorkspace::G4GeometryWorkspace() 51 { 51 { 52 fpLogicalVolumeSIM= 52 fpLogicalVolumeSIM= 53 &const_cast<G4LVManager&>(G4LogicalVolum 53 &const_cast<G4LVManager&>(G4LogicalVolume::GetSubInstanceManager()); 54 fpPhysicalVolumeSIM= 54 fpPhysicalVolumeSIM= 55 &const_cast<G4PVManager&>( G4VPhysicalVo 55 &const_cast<G4PVManager&>( G4VPhysicalVolume::GetSubInstanceManager() ); 56 fpReplicaSIM= 56 fpReplicaSIM= 57 &const_cast<G4PVRManager&>(G4PVReplica:: 57 &const_cast<G4PVRManager&>(G4PVReplica::GetSubInstanceManager()); 58 fpRegionSIM= 58 fpRegionSIM= 59 &const_cast<G4RegionManager&>(G4Region:: 59 &const_cast<G4RegionManager&>(G4Region::GetSubInstanceManager()); 60 60 61 // Create a work area for Logical Volumes in 61 // Create a work area for Logical Volumes in this thread 62 // then capture its address 62 // then capture its address 63 // 63 // 64 InitialiseWorkspace(); 64 InitialiseWorkspace(); 65 65 66 fLogicalVolumeOffset = fpLogicalVolumeSIM->G 66 fLogicalVolumeOffset = fpLogicalVolumeSIM->GetOffset(); 67 67 68 fPhysicalVolumeOffset = fpPhysicalVolumeSIM- 68 fPhysicalVolumeOffset = fpPhysicalVolumeSIM->GetOffset(); 69 69 70 fReplicaOffset = fpReplicaSIM->GetOffset(); 70 fReplicaOffset = fpReplicaSIM->GetOffset(); 71 71 72 fRegionOffset = fpRegionSIM->GetOffset(); 72 fRegionOffset = fpRegionSIM->GetOffset(); 73 } 73 } 74 74 75 // ------------------------------------------- 75 // ---------------------------------------------------------------------- 76 // 76 // >> 77 G4GeometryWorkspace::~G4GeometryWorkspace() >> 78 { >> 79 } >> 80 >> 81 // ---------------------------------------------------------------------- >> 82 // 77 void 83 void 78 G4GeometryWorkspace::UseWorkspace() 84 G4GeometryWorkspace::UseWorkspace() 79 { 85 { 80 // Geometry related, split classes mechanism 86 // Geometry related, split classes mechanism: instantiate sub-instance 81 // for this thread 87 // for this thread 82 // 88 // 83 fpLogicalVolumeSIM->UseWorkArea(fLogicalVolu 89 fpLogicalVolumeSIM->UseWorkArea(fLogicalVolumeOffset); 84 fpPhysicalVolumeSIM->UseWorkArea(fPhysicalVo 90 fpPhysicalVolumeSIM->UseWorkArea(fPhysicalVolumeOffset); 85 91 86 fpReplicaSIM->UseWorkArea(fReplicaOffset); 92 fpReplicaSIM->UseWorkArea(fReplicaOffset); 87 fpRegionSIM->UseWorkArea(fRegionOffset); 93 fpRegionSIM->UseWorkArea(fRegionOffset); 88 94 89 // When recycling a workspace 95 // When recycling a workspace 90 // - it must be a lightweight operation, t 96 // - it must be a lightweight operation, to reuse a valid work area 91 // - so it must NOT Initialise anything! 97 // - so it must NOT Initialise anything! 92 // Do not call InitialisePhysicalVolumes(); 98 // Do not call InitialisePhysicalVolumes(); 93 } 99 } 94 100 95 // ------------------------------------------- 101 // ---------------------------------------------------------------------- 96 // 102 // 97 void G4GeometryWorkspace::ReleaseWorkspace() 103 void G4GeometryWorkspace::ReleaseWorkspace() 98 { 104 { 99 fpLogicalVolumeSIM->UseWorkArea(nullptr); 105 fpLogicalVolumeSIM->UseWorkArea(nullptr); 100 fpPhysicalVolumeSIM->UseWorkArea(nullptr); 106 fpPhysicalVolumeSIM->UseWorkArea(nullptr); 101 107 102 fpReplicaSIM->UseWorkArea(nullptr); 108 fpReplicaSIM->UseWorkArea(nullptr); 103 fpRegionSIM->UseWorkArea(nullptr); 109 fpRegionSIM->UseWorkArea(nullptr); 104 } 110 } 105 111 106 // ------------------------------------------- 112 // ---------------------------------------------------------------------- 107 // 113 // 108 void G4GeometryWorkspace::InitialisePhysicalVo 114 void G4GeometryWorkspace::InitialisePhysicalVolumes() 109 { 115 { 110 G4PhysicalVolumeStore* physVolStore = G4Phys 116 G4PhysicalVolumeStore* physVolStore = G4PhysicalVolumeStore::GetInstance(); 111 for (auto physVol : *physVolStore) << 117 for (std::size_t ip=0; ip<physVolStore->size(); ++ip) 112 { 118 { >> 119 G4VPhysicalVolume* physVol = (*physVolStore)[ip]; 113 G4LogicalVolume *logicalVol = physVol->Get 120 G4LogicalVolume *logicalVol = physVol->GetLogicalVolume(); 114 121 115 // Use shadow pointer 122 // Use shadow pointer 116 // 123 // 117 G4VSolid* solid = logicalVol->GetMasterSol 124 G4VSolid* solid = logicalVol->GetMasterSolid(); 118 auto g4PVReplica = dynamic_cast<G4PVReplic << 125 G4PVReplica* g4PVReplica = dynamic_cast<G4PVReplica*>(physVol); 119 if (g4PVReplica == nullptr) 126 if (g4PVReplica == nullptr) 120 { 127 { 121 // Placement volume 128 // Placement volume 122 // 129 // 123 logicalVol->InitialiseWorker(logicalVol, 130 logicalVol->InitialiseWorker(logicalVol,solid,nullptr); 124 } 131 } 125 else 132 else 126 { 133 { 127 g4PVReplica->InitialiseWorker(g4PVReplic 134 g4PVReplica->InitialiseWorker(g4PVReplica); 128 logicalVol->InitialiseWorker(logicalVol, 135 logicalVol->InitialiseWorker(logicalVol,solid,nullptr); 129 136 130 // If the replica's solid (in LV) is cha 137 // If the replica's solid (in LV) is changed during navigation, 131 // it must be thread-private 138 // it must be thread-private 132 // 139 // 133 CloneReplicaSolid( g4PVReplica ); 140 CloneReplicaSolid( g4PVReplica ); 134 } 141 } 135 } 142 } 136 } 143 } 137 144 138 // ------------------------------------------- 145 // ---------------------------------------------------------------------- 139 // Create a clone of the solid for this replic 146 // Create a clone of the solid for this replica in this thread 140 // 147 // 141 G4bool G4GeometryWorkspace::CloneReplicaSolid( 148 G4bool G4GeometryWorkspace::CloneReplicaSolid( G4PVReplica* replicaPV ) 142 { 149 { 143 G4LogicalVolume* logicalV = replicaPV->GetLo 150 G4LogicalVolume* logicalV = replicaPV->GetLogicalVolume(); 144 G4VSolid* solid = logicalV->GetSolid(); 151 G4VSolid* solid = logicalV->GetSolid(); 145 152 146 G4AutoLock aLock(&mutex_init); 153 G4AutoLock aLock(&mutex_init); 147 G4VSolid* workerSolid = solid->Clone(); 154 G4VSolid* workerSolid = solid->Clone(); 148 aLock.unlock(); 155 aLock.unlock(); 149 156 150 if( workerSolid != nullptr ) 157 if( workerSolid != nullptr ) 151 { 158 { 152 logicalV->InitialiseWorker(logicalV,worker 159 logicalV->InitialiseWorker(logicalV,workerSolid,nullptr); 153 } 160 } 154 else 161 else 155 { 162 { 156 // In the case that not all solids support 163 // In the case that not all solids support(ed) the Clone() 157 // method, we do similar thing here to dyn 164 // method, we do similar thing here to dynamically cast 158 // and then get the clone method 165 // and then get the clone method 159 // 166 // 160 G4ExceptionDescription ed; 167 G4ExceptionDescription ed; 161 ed << "ERROR - Unable to initialise geomet 168 ed << "ERROR - Unable to initialise geometry for worker node." << "\n" 162 << "A solid lacks the Clone() method - 169 << "A solid lacks the Clone() method - or Clone() failed." << "\n" 163 << " Type of solid: " << solid->GetEn 170 << " Type of solid: " << solid->GetEntityType() << "\n" 164 << " Parameters: " << *solid; 171 << " Parameters: " << *solid; 165 G4Exception("G4GeometryWorkspace::CloneRep 172 G4Exception("G4GeometryWorkspace::CloneReplicaSolid()", 166 "GeomVol0003", FatalException, 173 "GeomVol0003", FatalException, ed); 167 return false; 174 return false; 168 } 175 } 169 return true; // It Worked 176 return true; // It Worked 170 } 177 } 171 178 172 // ------------------------------------------- 179 // ---------------------------------------------------------------------- 173 // 180 // 174 void G4GeometryWorkspace::InitialiseWorkspace( 181 void G4GeometryWorkspace::InitialiseWorkspace() 175 { 182 { 176 // Geometry related, split classes mechanism 183 // Geometry related, split classes mechanism: 177 // Do *NOT* instantiate sub-instance for thi 184 // Do *NOT* instantiate sub-instance for this thread, just copy the contents! 178 // 185 // 179 fpLogicalVolumeSIM->SlaveCopySubInstanceArra 186 fpLogicalVolumeSIM->SlaveCopySubInstanceArray(); 180 fpPhysicalVolumeSIM->SlaveCopySubInstanceArr 187 fpPhysicalVolumeSIM->SlaveCopySubInstanceArray(); 181 fpReplicaSIM->SlaveCopySubInstanceArray(); 188 fpReplicaSIM->SlaveCopySubInstanceArray(); 182 fpRegionSIM->SlaveInitializeSubInstance(); 189 fpRegionSIM->SlaveInitializeSubInstance(); 183 190 184 InitialisePhysicalVolumes(); 191 InitialisePhysicalVolumes(); 185 } 192 } 186 193 187 // ------------------------------------------- 194 // ---------------------------------------------------------------------- 188 // 195 // 189 void G4GeometryWorkspace::DestroyWorkspace() 196 void G4GeometryWorkspace::DestroyWorkspace() 190 { 197 { 191 G4PhysicalVolumeStore* physVolStore = G4Phys 198 G4PhysicalVolumeStore* physVolStore = G4PhysicalVolumeStore::GetInstance(); 192 for (auto physVol : *physVolStore) << 199 for (std::size_t ip=0; ip<physVolStore->size(); ++ip) 193 { 200 { >> 201 G4VPhysicalVolume* physVol = (*physVolStore)[ip]; 194 G4LogicalVolume* logicalVol = physVol->Get 202 G4LogicalVolume* logicalVol = physVol->GetLogicalVolume(); 195 auto g4PVReplica = dynamic_cast<G4PVReplic << 203 G4PVReplica* g4PVReplica = dynamic_cast<G4PVReplica*>(physVol); 196 if (g4PVReplica != nullptr) 204 if (g4PVReplica != nullptr) 197 { 205 { 198 g4PVReplica->TerminateWorker(g4PVReplica 206 g4PVReplica->TerminateWorker(g4PVReplica); 199 } 207 } 200 logicalVol->TerminateWorker(logicalVol); 208 logicalVol->TerminateWorker(logicalVol); 201 } 209 } 202 210 203 // Threads may attempt to free memory simult 211 // Threads may attempt to free memory simultaneously. 204 // Need a lock to guarantee thread safety 212 // Need a lock to guarantee thread safety 205 // 213 // 206 G4AutoLock aLock(&mutex_init); 214 G4AutoLock aLock(&mutex_init); 207 fpLogicalVolumeSIM->FreeSlave(); 215 fpLogicalVolumeSIM->FreeSlave(); 208 fpPhysicalVolumeSIM->FreeSlave(); 216 fpPhysicalVolumeSIM->FreeSlave(); 209 fpReplicaSIM->FreeSlave(); 217 fpReplicaSIM->FreeSlave(); 210 fpRegionSIM->FreeSlave(); 218 fpRegionSIM->FreeSlave(); 211 aLock.unlock(); 219 aLock.unlock(); 212 } 220 } 213 221