EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4PhysicalVolumeStore.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4PhysicalVolumeStore.cc
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 // G4PhysicalVolumeStore implementation
27 //
28 // 25.07.95, P.Kent, G.Cosmo
29 // --------------------------------------------------------------------
30 
31 #include "G4Types.hh"
32 #include "G4PhysicalVolumeStore.hh"
33 #include "G4GeometryManager.hh"
34 #include "G4LogicalVolume.hh"
35 
36 #include "G4AutoLock.hh"
37 
38 namespace
39 {
40  G4Mutex mapMutex = G4MUTEX_INITIALIZER;
41 }
42 
43 // ***************************************************************************
44 // Static class variables
45 // ***************************************************************************
46 //
48 G4ThreadLocal G4VStoreNotifier* G4PhysicalVolumeStore::fgNotifier = nullptr;
49 G4ThreadLocal G4bool G4PhysicalVolumeStore::locked = false;
50 
51 // ***************************************************************************
52 // Protected constructor: Construct underlying container with
53 // initial size of 100 entries
54 // ***************************************************************************
55 //
57  : std::vector<G4VPhysicalVolume*>()
58 {
59  reserve(100);
60 }
61 
62 // ***************************************************************************
63 // Destructor
64 // ***************************************************************************
65 //
67 {
68  Clean(); // Delete all volumes in the store
69  G4VPhysicalVolume::Clean(); // Delete allocated sub-instance data
70 }
71 
72 // ***************************************************************************
73 // Delete all elements from the store
74 // ***************************************************************************
75 //
77 {
78  // Do nothing if geometry is closed
79  //
80  if (G4GeometryManager::IsGeometryClosed())
81  {
82  G4cout << "WARNING - Attempt to delete the physical volume store"
83  << " while geometry closed !" << G4endl;
84  return;
85  }
86 
87  // Locks store for deletion of volumes. De-registration will be
88  // performed at this stage. G4VPhysicalVolumes will not de-register
89  // themselves.
90  //
91  locked = true;
92 
93  std::size_t i=0;
95 
96 #ifdef G4GEOMETRY_VOXELDEBUG
97  G4cout << "Deleting Physical Volumes ... ";
98 #endif
99 
100  for(auto pos=store->cbegin(); pos!=store->cend(); ++pos)
101  {
102  if (fgNotifier != nullptr) { fgNotifier->NotifyDeRegistration(); }
103  delete *pos; ++i;
104  }
105 
106 #ifdef G4GEOMETRY_VOXELDEBUG
107  if (store->size() < i-1)
108  { G4cout << "No volumes deleted. Already deleted by user ?" << G4endl; }
109  else
110  { G4cout << i-1 << " volumes deleted !" << G4endl; }
111 #endif
112 
113  store->bmap.clear(); store->mvalid = false;
114  locked = false;
115  store->clear();
116 }
117 
118 // ***************************************************************************
119 // Associate user notifier to the store
120 // ***************************************************************************
121 //
122 void G4PhysicalVolumeStore::SetNotifier(G4VStoreNotifier* pNotifier)
123 {
124  GetInstance();
125  fgNotifier = pNotifier;
126 }
127 
128 // ***************************************************************************
129 // Bring contents of internal map up to date and reset validity flag
130 // ***************************************************************************
131 //
133 {
134  G4AutoLock l(&mapMutex); // to avoid thread contention at initialisation
135  if (mvalid) return;
136  bmap.clear();
137  for(auto pos=GetInstance()->cbegin(); pos!=GetInstance()->cend(); ++pos)
138  {
139  const G4String& vol_name = (*pos)->GetName();
140  auto it = bmap.find(vol_name);
141  if (it != bmap.cend())
142  {
143  it->second.push_back(*pos);
144  }
145  else
146  {
147  std::vector<G4VPhysicalVolume*> vol_vec { *pos };
148  bmap.insert(std::make_pair(vol_name, vol_vec));
149  }
150  }
151  mvalid = true;
152  l.unlock();
153 }
154 
155 // ***************************************************************************
156 // Add Volume to container
157 // ***************************************************************************
158 //
159 void G4PhysicalVolumeStore::Register(G4VPhysicalVolume* pVolume)
160 {
162  store->push_back(pVolume);
163  const G4String& vol_name = pVolume->GetName();
164  auto it = store->bmap.find(vol_name);
165  if (it != store->bmap.cend())
166  {
167  it->second.push_back(pVolume);
168  }
169  else
170  {
171  std::vector<G4VPhysicalVolume*> vol_vec { pVolume };
172  store->bmap.insert(std::make_pair(vol_name, vol_vec));
173  }
174  if (fgNotifier) { fgNotifier->NotifyRegistration(); }
175  store->mvalid = true;
176 }
177 
178 // ***************************************************************************
179 // Remove Volume from container and update the list of daughters
180 // of the mother's logical volume
181 // ***************************************************************************
182 //
183 void G4PhysicalVolumeStore::DeRegister(G4VPhysicalVolume* pVolume)
184 {
186  if (!locked) // Do not de-register if locked !
187  {
188  if (fgNotifier != nullptr) { fgNotifier->NotifyDeRegistration(); }
189  G4LogicalVolume* motherLogical = pVolume->GetMotherLogical();
190  if (motherLogical != nullptr) { motherLogical->RemoveDaughter(pVolume); }
191  for (auto i=store->cbegin(); i!=store->cend(); ++i)
192  {
193  if (**i==*pVolume)
194  {
195  store->erase(i);
196  break;
197  }
198  }
199  const G4String& vol_name = pVolume->GetName();
200  auto it = store->bmap.find(vol_name);
201  if (it != store->bmap.cend())
202  {
203  if (it->second.size() > 1)
204  {
205  for (auto i=it->second.cbegin(); i!=it->second.cend(); ++i)
206  {
207  if (**i==*pVolume)
208  {
209  it->second.erase(i);
210  break;
211  }
212  }
213  }
214  else
215  {
216  store->bmap.erase(it);
217  }
218  }
219  }
220 }
221 
222 // ***************************************************************************
223 // Retrieve the first or last volume pointer in the container having that name
224 // ***************************************************************************
225 //
226 G4VPhysicalVolume*
228  G4bool reverseSearch) const
229 {
231  if (!store->mvalid) { store->UpdateMap(); }
232  auto pos = store->bmap.find(name);
233  if(pos != store->bmap.cend())
234  {
235  if ((verbose) && (pos->second.size()>1))
236  {
237  std::ostringstream message;
238  message << "There exists more than ONE physical volume in store named: "
239  << name << "!" << G4endl
240  << "Returning the first found.";
241  G4Exception("G4PhysicalVolumeStore::GetVolume()",
242  "GeomMgt1001", JustWarning, message);
243  }
244  if(reverseSearch)
245  {
246  return pos->second[pos->second.size()-1];
247  }
248  else
249  {
250  return pos->second[0];
251  }
252  }
253  if (verbose)
254  {
255  std::ostringstream message;
256  message << "Volume NOT found in store !" << G4endl
257  << " Volume " << name << " NOT found in store !" << G4endl
258  << " Returning NULL pointer.";
259  G4Exception("G4PhysicalVolumeStore::GetVolume()",
260  "GeomMgt1001", JustWarning, message);
261  }
262  return nullptr;
263 }
264 
265 // ***************************************************************************
266 // Return ptr to Store, setting if necessary
267 // ***************************************************************************
268 //
270 {
271  static G4PhysicalVolumeStore worldStore;
272  if (fgInstance == nullptr)
273  {
274  fgInstance = &worldStore;
275  }
276  return fgInstance;
277 }