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 // G4PhysicalVolumeStore implementation 26 // G4PhysicalVolumeStore implementation 27 // 27 // 28 // 25.07.95, P.Kent, G.Cosmo 28 // 25.07.95, P.Kent, G.Cosmo 29 // ------------------------------------------- 29 // -------------------------------------------------------------------- 30 30 31 #include "G4Types.hh" 31 #include "G4Types.hh" 32 #include "G4PhysicalVolumeStore.hh" 32 #include "G4PhysicalVolumeStore.hh" 33 #include "G4GeometryManager.hh" 33 #include "G4GeometryManager.hh" 34 #include "G4LogicalVolume.hh" 34 #include "G4LogicalVolume.hh" 35 35 36 #include "G4AutoLock.hh" 36 #include "G4AutoLock.hh" 37 37 38 namespace 38 namespace 39 { 39 { 40 G4Mutex mapMutex = G4MUTEX_INITIALIZER; 40 G4Mutex mapMutex = G4MUTEX_INITIALIZER; 41 } 41 } 42 42 43 // ******************************************* 43 // *************************************************************************** 44 // Static class variables 44 // Static class variables 45 // ******************************************* 45 // *************************************************************************** 46 // 46 // 47 G4PhysicalVolumeStore* G4PhysicalVolumeStore:: 47 G4PhysicalVolumeStore* G4PhysicalVolumeStore::fgInstance = nullptr; 48 G4ThreadLocal G4VStoreNotifier* G4PhysicalVolu 48 G4ThreadLocal G4VStoreNotifier* G4PhysicalVolumeStore::fgNotifier = nullptr; 49 G4ThreadLocal G4bool G4PhysicalVolumeStore::lo 49 G4ThreadLocal G4bool G4PhysicalVolumeStore::locked = false; 50 50 51 // ******************************************* 51 // *************************************************************************** 52 // Protected constructor: Construct underlying 52 // Protected constructor: Construct underlying container with 53 // initial size of 100 entries 53 // initial size of 100 entries 54 // ******************************************* 54 // *************************************************************************** 55 // 55 // 56 G4PhysicalVolumeStore::G4PhysicalVolumeStore() 56 G4PhysicalVolumeStore::G4PhysicalVolumeStore() 57 << 57 : std::vector<G4VPhysicalVolume*>() 58 { 58 { 59 reserve(100); 59 reserve(100); 60 } 60 } 61 61 62 // ******************************************* 62 // *************************************************************************** 63 // Destructor 63 // Destructor 64 // ******************************************* 64 // *************************************************************************** 65 // 65 // 66 G4PhysicalVolumeStore::~G4PhysicalVolumeStore( 66 G4PhysicalVolumeStore::~G4PhysicalVolumeStore() 67 { 67 { 68 Clean(); // Delete all volumes in the store 68 Clean(); // Delete all volumes in the store 69 G4VPhysicalVolume::Clean(); // Delete alloc 69 G4VPhysicalVolume::Clean(); // Delete allocated sub-instance data 70 } 70 } 71 71 72 // ******************************************* 72 // *************************************************************************** 73 // Delete all elements from the store 73 // Delete all elements from the store 74 // ******************************************* 74 // *************************************************************************** 75 // 75 // 76 void G4PhysicalVolumeStore::Clean() 76 void G4PhysicalVolumeStore::Clean() 77 { 77 { 78 // Do nothing if geometry is closed 78 // Do nothing if geometry is closed 79 // 79 // 80 if (G4GeometryManager::GetInstance()->IsGeom << 80 if (G4GeometryManager::IsGeometryClosed()) 81 { 81 { 82 G4cout << "WARNING - Attempt to delete the 82 G4cout << "WARNING - Attempt to delete the physical volume store" 83 << " while geometry closed !" << G4 83 << " while geometry closed !" << G4endl; 84 return; 84 return; 85 } 85 } 86 86 87 // Locks store for deletion of volumes. De-r 87 // Locks store for deletion of volumes. De-registration will be 88 // performed at this stage. G4VPhysicalVolum 88 // performed at this stage. G4VPhysicalVolumes will not de-register 89 // themselves. 89 // themselves. 90 // 90 // 91 locked = true; 91 locked = true; 92 92 93 G4PhysicalVolumeStore* store = GetInstance() 93 G4PhysicalVolumeStore* store = GetInstance(); 94 94 95 for(auto pos=store->cbegin(); pos!=store->ce 95 for(auto pos=store->cbegin(); pos!=store->cend(); ++pos) 96 { 96 { 97 if (fgNotifier != nullptr) { fgNotifier->N 97 if (fgNotifier != nullptr) { fgNotifier->NotifyDeRegistration(); } 98 delete *pos; 98 delete *pos; 99 } 99 } 100 100 101 store->bmap.clear(); store->mvalid = false; 101 store->bmap.clear(); store->mvalid = false; 102 locked = false; 102 locked = false; 103 store->clear(); 103 store->clear(); 104 } 104 } 105 105 106 // ******************************************* 106 // *************************************************************************** 107 // Associate user notifier to the store 107 // Associate user notifier to the store 108 // ******************************************* 108 // *************************************************************************** 109 // 109 // 110 void G4PhysicalVolumeStore::SetNotifier(G4VSto 110 void G4PhysicalVolumeStore::SetNotifier(G4VStoreNotifier* pNotifier) 111 { 111 { 112 GetInstance(); 112 GetInstance(); 113 fgNotifier = pNotifier; 113 fgNotifier = pNotifier; 114 } 114 } 115 115 116 // ******************************************* 116 // *************************************************************************** 117 // Bring contents of internal map up to date a 117 // Bring contents of internal map up to date and reset validity flag 118 // ******************************************* 118 // *************************************************************************** 119 // 119 // 120 void G4PhysicalVolumeStore::UpdateMap() 120 void G4PhysicalVolumeStore::UpdateMap() 121 { 121 { 122 G4AutoLock l(&mapMutex); // to avoid thread 122 G4AutoLock l(&mapMutex); // to avoid thread contention at initialisation 123 if (mvalid) return; 123 if (mvalid) return; 124 bmap.clear(); 124 bmap.clear(); 125 for(auto pos=GetInstance()->cbegin(); pos!=G 125 for(auto pos=GetInstance()->cbegin(); pos!=GetInstance()->cend(); ++pos) 126 { 126 { 127 const G4String& vol_name = (*pos)->GetName 127 const G4String& vol_name = (*pos)->GetName(); 128 auto it = bmap.find(vol_name); 128 auto it = bmap.find(vol_name); 129 if (it != bmap.cend()) 129 if (it != bmap.cend()) 130 { 130 { 131 it->second.push_back(*pos); 131 it->second.push_back(*pos); 132 } 132 } 133 else 133 else 134 { 134 { 135 std::vector<G4VPhysicalVolume*> vol_vec 135 std::vector<G4VPhysicalVolume*> vol_vec { *pos }; 136 bmap.insert(std::make_pair(vol_name, vol 136 bmap.insert(std::make_pair(vol_name, vol_vec)); 137 } 137 } 138 } 138 } 139 mvalid = true; 139 mvalid = true; 140 l.unlock(); 140 l.unlock(); 141 } 141 } 142 142 143 // ******************************************* 143 // *************************************************************************** 144 // Add Volume to container 144 // Add Volume to container 145 // ******************************************* 145 // *************************************************************************** 146 // 146 // 147 void G4PhysicalVolumeStore::Register(G4VPhysic 147 void G4PhysicalVolumeStore::Register(G4VPhysicalVolume* pVolume) 148 { 148 { 149 G4PhysicalVolumeStore* store = GetInstance() 149 G4PhysicalVolumeStore* store = GetInstance(); 150 store->push_back(pVolume); 150 store->push_back(pVolume); 151 const G4String& vol_name = pVolume->GetName( 151 const G4String& vol_name = pVolume->GetName(); 152 auto it = store->bmap.find(vol_name); 152 auto it = store->bmap.find(vol_name); 153 if (it != store->bmap.cend()) 153 if (it != store->bmap.cend()) 154 { 154 { 155 it->second.push_back(pVolume); 155 it->second.push_back(pVolume); 156 } 156 } 157 else 157 else 158 { 158 { 159 std::vector<G4VPhysicalVolume*> vol_vec { 159 std::vector<G4VPhysicalVolume*> vol_vec { pVolume }; 160 store->bmap.insert(std::make_pair(vol_name 160 store->bmap.insert(std::make_pair(vol_name, vol_vec)); 161 } 161 } 162 if (fgNotifier != nullptr) { fgNotifier->Not << 162 if (fgNotifier) { fgNotifier->NotifyRegistration(); } 163 store->mvalid = true; 163 store->mvalid = true; 164 } 164 } 165 165 166 // ******************************************* 166 // *************************************************************************** 167 // Remove Volume from container and update the 167 // Remove Volume from container and update the list of daughters 168 // of the mother's logical volume 168 // of the mother's logical volume 169 // ******************************************* 169 // *************************************************************************** 170 // 170 // 171 void G4PhysicalVolumeStore::DeRegister(G4VPhys 171 void G4PhysicalVolumeStore::DeRegister(G4VPhysicalVolume* pVolume) 172 { 172 { 173 G4PhysicalVolumeStore* store = GetInstance() 173 G4PhysicalVolumeStore* store = GetInstance(); 174 if (!locked) // Do not de-register if loc 174 if (!locked) // Do not de-register if locked ! 175 { 175 { 176 if (fgNotifier != nullptr) { fgNotifier->N 176 if (fgNotifier != nullptr) { fgNotifier->NotifyDeRegistration(); } 177 G4LogicalVolume* motherLogical = pVolume-> 177 G4LogicalVolume* motherLogical = pVolume->GetMotherLogical(); 178 if (motherLogical != nullptr) { motherLogi 178 if (motherLogical != nullptr) { motherLogical->RemoveDaughter(pVolume); } 179 for (auto i=store->cbegin(); i!=store->cen 179 for (auto i=store->cbegin(); i!=store->cend(); ++i) 180 { 180 { 181 if (**i==*pVolume) 181 if (**i==*pVolume) 182 { 182 { 183 store->erase(i); 183 store->erase(i); 184 break; 184 break; 185 } 185 } 186 } 186 } 187 const G4String& vol_name = pVolume->GetNam 187 const G4String& vol_name = pVolume->GetName(); 188 auto it = store->bmap.find(vol_name); 188 auto it = store->bmap.find(vol_name); 189 if (it != store->bmap.cend()) 189 if (it != store->bmap.cend()) 190 { 190 { 191 if (it->second.size() > 1) 191 if (it->second.size() > 1) 192 { 192 { 193 for (auto i=it->second.cbegin(); i!=it 193 for (auto i=it->second.cbegin(); i!=it->second.cend(); ++i) 194 { 194 { 195 if (**i==*pVolume) 195 if (**i==*pVolume) 196 { 196 { 197 it->second.erase(i); 197 it->second.erase(i); 198 break; 198 break; 199 } 199 } 200 } 200 } 201 } 201 } 202 else 202 else 203 { 203 { 204 store->bmap.erase(it); 204 store->bmap.erase(it); 205 } 205 } 206 } 206 } 207 } 207 } 208 } 208 } 209 209 210 // ******************************************* 210 // *************************************************************************** 211 // Retrieve the first or last volume pointer i 211 // Retrieve the first or last volume pointer in the container having that name 212 // ******************************************* 212 // *************************************************************************** 213 // 213 // 214 G4VPhysicalVolume* 214 G4VPhysicalVolume* 215 G4PhysicalVolumeStore::GetVolume(const G4Strin 215 G4PhysicalVolumeStore::GetVolume(const G4String& name, G4bool verbose, 216 G4bool revers 216 G4bool reverseSearch) const 217 { 217 { 218 G4PhysicalVolumeStore* store = GetInstance() 218 G4PhysicalVolumeStore* store = GetInstance(); 219 if (!store->mvalid) { store->UpdateMap(); } 219 if (!store->mvalid) { store->UpdateMap(); } 220 auto pos = store->bmap.find(name); 220 auto pos = store->bmap.find(name); 221 if(pos != store->bmap.cend()) 221 if(pos != store->bmap.cend()) 222 { 222 { 223 if ((verbose) && (pos->second.size()>1)) 223 if ((verbose) && (pos->second.size()>1)) 224 { 224 { 225 std::ostringstream message; 225 std::ostringstream message; 226 message << "There exists more than ONE p 226 message << "There exists more than ONE physical volume in store named: " 227 << name << "!" << G4endl 227 << name << "!" << G4endl 228 << "Returning the first found."; 228 << "Returning the first found."; 229 G4Exception("G4PhysicalVolumeStore::GetV 229 G4Exception("G4PhysicalVolumeStore::GetVolume()", 230 "GeomMgt1001", JustWarning, 230 "GeomMgt1001", JustWarning, message); 231 } 231 } 232 if(reverseSearch) 232 if(reverseSearch) 233 { 233 { 234 return pos->second[pos->second.size()-1] 234 return pos->second[pos->second.size()-1]; 235 } 235 } 236 else 236 else 237 { 237 { 238 return pos->second[0]; 238 return pos->second[0]; 239 } 239 } 240 } 240 } 241 if (verbose) 241 if (verbose) 242 { 242 { 243 std::ostringstream message; 243 std::ostringstream message; 244 message << "Volume NOT found in store !" 244 message << "Volume NOT found in store !" << G4endl 245 << " Volume " << name << " 245 << " Volume " << name << " NOT found in store !" << G4endl 246 << " Returning NULL pointer 246 << " Returning NULL pointer."; 247 G4Exception("G4PhysicalVolumeStore::GetVo 247 G4Exception("G4PhysicalVolumeStore::GetVolume()", 248 "GeomMgt1001", JustWarning, m 248 "GeomMgt1001", JustWarning, message); 249 } 249 } 250 return nullptr; 250 return nullptr; 251 } 251 } 252 252 253 // ******************************************* 253 // *************************************************************************** 254 // Return ptr to Store, setting if necessary 254 // Return ptr to Store, setting if necessary 255 // ******************************************* 255 // *************************************************************************** 256 // 256 // 257 G4PhysicalVolumeStore* G4PhysicalVolumeStore:: 257 G4PhysicalVolumeStore* G4PhysicalVolumeStore::GetInstance() 258 { 258 { 259 static G4PhysicalVolumeStore worldStore; 259 static G4PhysicalVolumeStore worldStore; 260 if (fgInstance == nullptr) 260 if (fgInstance == nullptr) 261 { 261 { 262 fgInstance = &worldStore; 262 fgInstance = &worldStore; 263 } 263 } 264 return fgInstance; 264 return fgInstance; 265 } 265 } 266 266