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 // class G4LogicalVolume implementation 26 // class G4LogicalVolume implementation 27 // 27 // 28 // 15.01.13 G.Cosmo, A.Dotti: Modified for thr 28 // 15.01.13 G.Cosmo, A.Dotti: Modified for thread-safety for MT 29 // 01.03.05 G.Santin: Added flag for optional 29 // 01.03.05 G.Santin: Added flag for optional propagation of GetMass() 30 // 17.05.02 G.Cosmo: Added flag for optional o 30 // 17.05.02 G.Cosmo: Added flag for optional optimisation 31 // 12.02.99 S.Giani: Default initialization of 31 // 12.02.99 S.Giani: Default initialization of voxelization quality 32 // 04.08.97 P.M.DeFreitas: Added methods for p 32 // 04.08.97 P.M.DeFreitas: Added methods for parameterised simulation 33 // 11.07.95 P.Kent: Initial version 33 // 11.07.95 P.Kent: Initial version 34 // ------------------------------------------- 34 // -------------------------------------------------------------------- 35 35 36 #include "G4LogicalVolume.hh" 36 #include "G4LogicalVolume.hh" 37 #include "G4LogicalVolumeStore.hh" 37 #include "G4LogicalVolumeStore.hh" 38 #include "G4VSolid.hh" 38 #include "G4VSolid.hh" 39 #include "G4Material.hh" 39 #include "G4Material.hh" 40 #include "G4VPVParameterisation.hh" 40 #include "G4VPVParameterisation.hh" 41 #include "G4VisAttributes.hh" 41 #include "G4VisAttributes.hh" 42 42 43 #include "G4UnitsTable.hh" 43 #include "G4UnitsTable.hh" 44 44 45 G4LVData::G4LVData() {;} 45 G4LVData::G4LVData() {;} 46 46 47 // This new field helps to use the class G4LVM 47 // This new field helps to use the class G4LVManager 48 // 48 // 49 G4LVManager G4LogicalVolume::subInstanceManage 49 G4LVManager G4LogicalVolume::subInstanceManager; 50 50 51 // These macros change the references to field 51 // These macros change the references to fields that are now encapsulated 52 // in the class G4LVData. 52 // in the class G4LVData. 53 // 53 // 54 #define G4MT_solid ((subInstanceManager.of 54 #define G4MT_solid ((subInstanceManager.offset[instanceID]).fSolid) 55 #define G4MT_sdetector ((subInstanceManager.of 55 #define G4MT_sdetector ((subInstanceManager.offset[instanceID]).fSensitiveDetector) 56 #define G4MT_fmanager ((subInstanceManager.of 56 #define G4MT_fmanager ((subInstanceManager.offset[instanceID]).fFieldManager) 57 #define G4MT_material ((subInstanceManager.of 57 #define G4MT_material ((subInstanceManager.offset[instanceID]).fMaterial) 58 #define G4MT_mass ((subInstanceManager.of 58 #define G4MT_mass ((subInstanceManager.offset[instanceID]).fMass) 59 #define G4MT_ccouple ((subInstanceManager.of 59 #define G4MT_ccouple ((subInstanceManager.offset[instanceID]).fCutsCouple) 60 #define G4MT_instance (subInstanceManager.off 60 #define G4MT_instance (subInstanceManager.offset[instanceID]) 61 61 62 // ******************************************* 62 // ******************************************************************** 63 // Constructor - sets member data and adds to 63 // Constructor - sets member data and adds to logical Store, 64 // voxel pointer for optimisatio 64 // voxel pointer for optimisation set to 0 by default. 65 // Initialises daughter vector t 65 // Initialises daughter vector to 0 length. 66 // ******************************************* 66 // ******************************************************************** 67 // 67 // 68 G4LogicalVolume::G4LogicalVolume( G4VSolid* pS 68 G4LogicalVolume::G4LogicalVolume( G4VSolid* pSolid, 69 G4Material* 69 G4Material* pMaterial, 70 const G4String& na 70 const G4String& name, 71 G4FieldManag 71 G4FieldManager* pFieldMgr, 72 G4VSensitive 72 G4VSensitiveDetector* pSDetector, 73 G4UserLimits 73 G4UserLimits* pULimits, 74 G4bool optim 74 G4bool optimise ) 75 : fDaughters(0,(G4VPhysicalVolume*)nullptr), 75 : fDaughters(0,(G4VPhysicalVolume*)nullptr), fDaughtersVolumeType(kNormal), 76 fOptimise(optimise) 76 fOptimise(optimise) 77 { 77 { 78 // Initialize 'Shadow'/master pointers - for 78 // Initialize 'Shadow'/master pointers - for use in copying to workers 79 // 79 // 80 fSolid = pSolid; 80 fSolid = pSolid; 81 fSensitiveDetector = pSDetector; 81 fSensitiveDetector = pSDetector; 82 fFieldManager = pFieldMgr; 82 fFieldManager = pFieldMgr; 83 83 84 instanceID = subInstanceManager.CreateSubIns 84 instanceID = subInstanceManager.CreateSubInstance(); 85 AssignFieldManager(pFieldMgr); 85 AssignFieldManager(pFieldMgr); 86 86 87 G4MT_mass = 0.; 87 G4MT_mass = 0.; 88 G4MT_ccouple = nullptr; 88 G4MT_ccouple = nullptr; 89 89 90 SetSolid(pSolid); 90 SetSolid(pSolid); 91 SetMaterial(pMaterial); 91 SetMaterial(pMaterial); 92 SetName(name); 92 SetName(name); 93 SetSensitiveDetector(pSDetector); 93 SetSensitiveDetector(pSDetector); 94 SetUserLimits(pULimits); 94 SetUserLimits(pULimits); 95 95 96 // Initialize 'Shadow' data structure - for 96 // Initialize 'Shadow' data structure - for use by object persistency 97 // 97 // 98 lvdata = new G4LVData(); 98 lvdata = new G4LVData(); 99 lvdata->fSolid = pSolid; 99 lvdata->fSolid = pSolid; 100 lvdata->fMaterial = pMaterial; 100 lvdata->fMaterial = pMaterial; 101 101 102 // 102 // 103 // Add to store 103 // Add to store 104 // 104 // 105 G4LogicalVolumeStore::Register(this); 105 G4LogicalVolumeStore::Register(this); 106 } 106 } 107 107 108 // ******************************************* 108 // ******************************************************************** 109 // Fake default constructor - sets only member 109 // Fake default constructor - sets only member data and allocates memory 110 // for usage restri 110 // for usage restricted to object persistency. 111 // ******************************************* 111 // ******************************************************************** 112 // 112 // 113 G4LogicalVolume::G4LogicalVolume( __void__& ) 113 G4LogicalVolume::G4LogicalVolume( __void__& ) 114 : fDaughters(0,(G4VPhysicalVolume*)nullptr), 114 : fDaughters(0,(G4VPhysicalVolume*)nullptr), fName("") 115 { 115 { 116 instanceID = subInstanceManager.CreateSubIns 116 instanceID = subInstanceManager.CreateSubInstance(); 117 117 118 SetSensitiveDetector(nullptr); // G4MT_sd 118 SetSensitiveDetector(nullptr); // G4MT_sdetector = nullptr; 119 SetFieldManager(nullptr, false); // G4MT_fm 119 SetFieldManager(nullptr, false); // G4MT_fmanager = nullptr; 120 120 121 G4MT_mass = 0.; 121 G4MT_mass = 0.; 122 G4MT_ccouple = nullptr; 122 G4MT_ccouple = nullptr; 123 123 124 // Add to store 124 // Add to store 125 // 125 // 126 G4LogicalVolumeStore::Register(this); 126 G4LogicalVolumeStore::Register(this); 127 } 127 } 128 128 129 // ******************************************* 129 // ******************************************************************** 130 // Destructor - Removes itself from solid Stor 130 // Destructor - Removes itself from solid Store 131 // NOTE: Not virtual 131 // NOTE: Not virtual 132 // ******************************************* 132 // ******************************************************************** 133 // 133 // 134 G4LogicalVolume::~G4LogicalVolume() 134 G4LogicalVolume::~G4LogicalVolume() 135 { 135 { 136 if (!fLock && fRootRegion) // De-register r 136 if (!fLock && fRootRegion) // De-register root region first if not locked 137 { // and flagged a 137 { // and flagged as root logical-volume 138 fRegion->RemoveRootLogicalVolume(this, tru 138 fRegion->RemoveRootLogicalVolume(this, true); 139 } 139 } 140 delete lvdata; 140 delete lvdata; 141 G4LogicalVolumeStore::DeRegister(this); 141 G4LogicalVolumeStore::DeRegister(this); 142 } 142 } 143 143 144 // ******************************************* 144 // ******************************************************************** 145 // SetName - Set volume name and notify store 145 // SetName - Set volume name and notify store of the change 146 // ******************************************* 146 // ******************************************************************** 147 // 147 // 148 void G4LogicalVolume::SetName(const G4String& 148 void G4LogicalVolume::SetName(const G4String& pName) 149 { 149 { 150 fName = pName; 150 fName = pName; 151 G4LogicalVolumeStore::GetInstance()->SetMapV 151 G4LogicalVolumeStore::GetInstance()->SetMapValid(false); 152 } 152 } 153 153 154 // ******************************************* 154 // ******************************************************************** 155 // InitialiseWorker 155 // InitialiseWorker 156 // 156 // 157 // This method is similar to the constructor. 157 // This method is similar to the constructor. It is used by each worker 158 // thread to achieve the same effect as that o 158 // thread to achieve the same effect as that of the master thread exept 159 // to register the new created instance. This 159 // to register the new created instance. This method is invoked explicitly. 160 // It does not create a new G4LogicalVolume in 160 // It does not create a new G4LogicalVolume instance. It only assign the value 161 // for the fields encapsulated by the class G4 161 // for the fields encapsulated by the class G4LVData. 162 // ******************************************* 162 // ******************************************************************** 163 // 163 // 164 void G4LogicalVolume:: 164 void G4LogicalVolume:: 165 InitialiseWorker( G4LogicalVolume* /*pMasterOb 165 InitialiseWorker( G4LogicalVolume* /*pMasterObject*/, 166 G4VSolid* pSolid, 166 G4VSolid* pSolid, 167 G4VSensitiveDetector* pSDete 167 G4VSensitiveDetector* pSDetector) 168 { 168 { 169 subInstanceManager.SlaveCopySubInstanceArray 169 subInstanceManager.SlaveCopySubInstanceArray(); 170 170 171 SetSolid(pSolid); 171 SetSolid(pSolid); 172 SetSensitiveDetector(pSDetector); // How th 172 SetSensitiveDetector(pSDetector); // How this object is available now ? 173 AssignFieldManager(fFieldManager); 173 AssignFieldManager(fFieldManager); 174 // Should be set - but a per-thread copy is 174 // Should be set - but a per-thread copy is not available yet 175 // Must not call SetFieldManager(), which p 175 // Must not call SetFieldManager(), which propagates FieldMgr 176 176 177 #ifdef CLONE_FIELD_MGR 177 #ifdef CLONE_FIELD_MGR 178 // Create a field FieldManager by cloning 178 // Create a field FieldManager by cloning 179 // 179 // 180 G4FieldManager workerFldMgr = fFieldManager- 180 G4FieldManager workerFldMgr = fFieldManager->GetWorkerClone(G4bool* created); 181 if( created || (GetFieldManager() != workerF 181 if( created || (GetFieldManager() != workerFldMgr) ) 182 { 182 { 183 SetFieldManager(fFieldManager, false); // 183 SetFieldManager(fFieldManager, false); // which propagates FieldMgr 184 } 184 } 185 else 185 else 186 { 186 { 187 // Field manager existed and is equal to c 187 // Field manager existed and is equal to current one 188 // 188 // 189 AssignFieldManager(workerFldMgr); 189 AssignFieldManager(workerFldMgr); 190 } 190 } 191 #endif 191 #endif 192 } 192 } 193 193 194 // ******************************************* 194 // ******************************************************************** 195 // Clean 195 // Clean 196 // ******************************************* 196 // ******************************************************************** 197 // 197 // 198 void G4LogicalVolume::Clean() 198 void G4LogicalVolume::Clean() 199 { 199 { 200 subInstanceManager.FreeSlave(); 200 subInstanceManager.FreeSlave(); 201 } 201 } 202 202 203 // ******************************************* 203 // ******************************************************************** 204 // TerminateWorker 204 // TerminateWorker 205 // 205 // 206 // This method is similar to the destructor. I 206 // This method is similar to the destructor. It is used by each worker 207 // thread to achieve the partial effect as tha 207 // thread to achieve the partial effect as that of the master thread. 208 // For G4LogicalVolume instances, nothing more 208 // For G4LogicalVolume instances, nothing more to do here. 209 // ******************************************* 209 // ******************************************************************** 210 // 210 // 211 void G4LogicalVolume:: 211 void G4LogicalVolume:: 212 TerminateWorker( G4LogicalVolume* /*pMasterObj 212 TerminateWorker( G4LogicalVolume* /*pMasterObject*/) 213 { 213 { 214 } 214 } 215 215 216 // ******************************************* 216 // ******************************************************************** 217 // GetSubInstanceManager 217 // GetSubInstanceManager 218 // 218 // 219 // Returns the private data instance manager. 219 // Returns the private data instance manager. 220 // ******************************************* 220 // ******************************************************************** 221 // 221 // 222 const G4LVManager& G4LogicalVolume::GetSubInst 222 const G4LVManager& G4LogicalVolume::GetSubInstanceManager() 223 { 223 { 224 return subInstanceManager; 224 return subInstanceManager; 225 } 225 } 226 226 227 // ******************************************* 227 // ******************************************************************** 228 // GetFieldManager 228 // GetFieldManager 229 // ******************************************* 229 // ******************************************************************** 230 // 230 // 231 G4FieldManager* G4LogicalVolume::GetFieldManag 231 G4FieldManager* G4LogicalVolume::GetFieldManager() const 232 { 232 { 233 return G4MT_fmanager; 233 return G4MT_fmanager; 234 } 234 } 235 235 236 // ******************************************* 236 // ******************************************************************** 237 // AssignFieldManager 237 // AssignFieldManager 238 // ******************************************* 238 // ******************************************************************** 239 // 239 // 240 void G4LogicalVolume::AssignFieldManager( G4Fi 240 void G4LogicalVolume::AssignFieldManager( G4FieldManager *fldMgr) 241 { 241 { 242 G4MT_fmanager= fldMgr; 242 G4MT_fmanager= fldMgr; 243 if(G4Threading::IsMasterThread()) { fFieldM 243 if(G4Threading::IsMasterThread()) { fFieldManager = fldMgr; } 244 } 244 } 245 245 246 // ******************************************* 246 // ******************************************************************** 247 // IsExtended 247 // IsExtended 248 // ******************************************* 248 // ******************************************************************** 249 // 249 // 250 G4bool G4LogicalVolume::IsExtended() const 250 G4bool G4LogicalVolume::IsExtended() const 251 { 251 { 252 return false; 252 return false; 253 } 253 } 254 254 255 // ******************************************* 255 // ******************************************************************** 256 // SetFieldManager 256 // SetFieldManager 257 // ******************************************* 257 // ******************************************************************** 258 // 258 // 259 void 259 void 260 G4LogicalVolume::SetFieldManager(G4FieldManage 260 G4LogicalVolume::SetFieldManager(G4FieldManager* pNewFieldMgr, 261 G4bool 261 G4bool forceAllDaughters) 262 { 262 { 263 AssignFieldManager(pNewFieldMgr); 263 AssignFieldManager(pNewFieldMgr); 264 264 265 auto NoDaughters = GetNoDaughters(); 265 auto NoDaughters = GetNoDaughters(); 266 while ( (NoDaughters--)>0 ) 266 while ( (NoDaughters--)>0 ) 267 { 267 { 268 G4LogicalVolume* DaughterLogVol; 268 G4LogicalVolume* DaughterLogVol; 269 DaughterLogVol = GetDaughter(NoDaughters)- 269 DaughterLogVol = GetDaughter(NoDaughters)->GetLogicalVolume(); 270 if ( forceAllDaughters || (DaughterLogVol- 270 if ( forceAllDaughters || (DaughterLogVol->GetFieldManager() == nullptr) ) 271 { 271 { 272 DaughterLogVol->SetFieldManager(pNewFiel 272 DaughterLogVol->SetFieldManager(pNewFieldMgr, forceAllDaughters); 273 } 273 } 274 } 274 } 275 } 275 } 276 276 277 // ******************************************* 277 // ******************************************************************** 278 // AddDaughter 278 // AddDaughter 279 // ******************************************* 279 // ******************************************************************** 280 // 280 // 281 void G4LogicalVolume::AddDaughter(G4VPhysicalV 281 void G4LogicalVolume::AddDaughter(G4VPhysicalVolume* pNewDaughter) 282 { 282 { 283 EVolume daughterType = pNewDaughter->VolumeT 283 EVolume daughterType = pNewDaughter->VolumeType(); 284 284 285 // The type of the navigation needed is dete 285 // The type of the navigation needed is determined by the first daughter 286 // 286 // 287 if( fDaughters.empty() ) 287 if( fDaughters.empty() ) 288 { 288 { 289 fDaughtersVolumeType = daughterType; 289 fDaughtersVolumeType = daughterType; 290 } 290 } 291 else 291 else 292 { 292 { 293 // Check consistency of detector descripti 293 // Check consistency of detector description 294 294 295 // 1. A replica or parameterised volume ca 295 // 1. A replica or parameterised volume can have only one daughter 296 // 296 // 297 if( fDaughters[0]->IsReplicated() ) 297 if( fDaughters[0]->IsReplicated() ) 298 { 298 { 299 std::ostringstream message; 299 std::ostringstream message; 300 message << "ERROR - Attempt to place a v 300 message << "ERROR - Attempt to place a volume in a mother volume" 301 << G4endl 301 << G4endl 302 << " already containing a repli 302 << " already containing a replicated volume." << G4endl 303 << " A volume can either contai 303 << " A volume can either contain several placements" << G4endl 304 << " or a unique replica or par 304 << " or a unique replica or parameterised volume !" << G4endl 305 << " Mother logical volume: 305 << " Mother logical volume: " << GetName() << G4endl 306 << " Placing volume: " << pN 306 << " Placing volume: " << pNewDaughter->GetName() 307 << G4endl; 307 << G4endl; 308 G4Exception("G4LogicalVolume::AddDaughte 308 G4Exception("G4LogicalVolume::AddDaughter()", "GeomMgt0002", 309 FatalException, message, 309 FatalException, message, 310 "Replica or parameterised vo 310 "Replica or parameterised volume must be the only daughter!"); 311 } 311 } 312 else 312 else 313 { 313 { 314 // 2. Ensure that Placement and External 314 // 2. Ensure that Placement and External physical volumes do not mix 315 // 315 // 316 if( daughterType != fDaughtersVolumeTyp 316 if( daughterType != fDaughtersVolumeType ) 317 { 317 { 318 std::ostringstream message; 318 std::ostringstream message; 319 message << "ERROR - Attempt to place a 319 message << "ERROR - Attempt to place a volume in a mother volume" 320 << G4endl 320 << G4endl 321 << " already containing a dif 321 << " already containing a different type of volume." << G4endl 322 << " A volume can either cont 322 << " A volume can either contain" << G4endl 323 << " - one or more placements 323 << " - one or more placements, OR" << G4endl 324 << " - one or more 'external' 324 << " - one or more 'external' type physical volumes." << G4endl 325 << " Mother logical volume: 325 << " Mother logical volume: " << GetName() << G4endl 326 << " Volume being placed: " 326 << " Volume being placed: " << pNewDaughter->GetName() 327 << G4endl; 327 << G4endl; 328 G4Exception("G4LogicalVolume::AddDaugh 328 G4Exception("G4LogicalVolume::AddDaughter()", "GeomMgt0002", 329 FatalException, message, 329 FatalException, message, 330 "Cannot mix placements and 330 "Cannot mix placements and external physical volumes !"); 331 } 331 } 332 } 332 } 333 } 333 } 334 334 335 // Invalidate previous calculation of mass - 335 // Invalidate previous calculation of mass - if any - for all threads 336 // 336 // 337 G4MT_mass = 0.; 337 G4MT_mass = 0.; 338 fDaughters.push_back(pNewDaughter); 338 fDaughters.push_back(pNewDaughter); 339 339 340 G4LogicalVolume* pDaughterLogical = pNewDaug 340 G4LogicalVolume* pDaughterLogical = pNewDaughter->GetLogicalVolume(); 341 341 342 // Propagate the Field Manager, if the daugh 342 // Propagate the Field Manager, if the daughter has no field Manager 343 // 343 // 344 G4FieldManager* pDaughterFieldManager = pDau 344 G4FieldManager* pDaughterFieldManager = pDaughterLogical->GetFieldManager(); 345 345 346 // Avoid propagating the fieldManager pointe 346 // Avoid propagating the fieldManager pointer if null 347 // and daughter's one is null as well... 347 // and daughter's one is null as well... 348 // 348 // 349 if( (G4MT_fmanager != nullptr ) && (pDaughte 349 if( (G4MT_fmanager != nullptr ) && (pDaughterFieldManager == nullptr) ) 350 { 350 { 351 pDaughterLogical->SetFieldManager(G4MT_fma 351 pDaughterLogical->SetFieldManager(G4MT_fmanager, false); 352 } 352 } 353 if (fRegion != nullptr) 353 if (fRegion != nullptr) 354 { 354 { 355 PropagateRegion(); 355 PropagateRegion(); 356 fRegion->RegionModified(true); 356 fRegion->RegionModified(true); 357 } 357 } 358 } 358 } 359 359 360 // ******************************************* 360 // ******************************************************************** 361 // RemoveDaughter 361 // RemoveDaughter 362 // ******************************************* 362 // ******************************************************************** 363 // 363 // 364 void G4LogicalVolume::RemoveDaughter(const G4V 364 void G4LogicalVolume::RemoveDaughter(const G4VPhysicalVolume* p) 365 { 365 { 366 for (auto i=fDaughters.cbegin(); i!=fDaughte 366 for (auto i=fDaughters.cbegin(); i!=fDaughters.cend(); ++i ) 367 { 367 { 368 if (**i==*p) 368 if (**i==*p) 369 { 369 { 370 fDaughters.erase(i); 370 fDaughters.erase(i); 371 break; 371 break; 372 } 372 } 373 } 373 } 374 if (fRegion != nullptr) 374 if (fRegion != nullptr) 375 { 375 { 376 fRegion->RegionModified(true); 376 fRegion->RegionModified(true); 377 } 377 } 378 G4MT_mass = 0.; 378 G4MT_mass = 0.; 379 } 379 } 380 380 381 // ******************************************* 381 // ******************************************************************** 382 // ClearDaughters 382 // ClearDaughters 383 // ******************************************* 383 // ******************************************************************** 384 // 384 // 385 void G4LogicalVolume::ClearDaughters() 385 void G4LogicalVolume::ClearDaughters() 386 { 386 { 387 fDaughters.erase(fDaughters.cbegin(), fDaugh 387 fDaughters.erase(fDaughters.cbegin(), fDaughters.cend()); 388 if (fRegion != nullptr) 388 if (fRegion != nullptr) 389 { 389 { 390 fRegion->RegionModified(true); 390 fRegion->RegionModified(true); 391 } 391 } 392 G4MT_mass = 0.; 392 G4MT_mass = 0.; 393 } 393 } 394 394 395 // ******************************************* 395 // ******************************************************************** 396 // ResetMass 396 // ResetMass 397 // ******************************************* 397 // ******************************************************************** 398 // 398 // 399 void G4LogicalVolume::ResetMass() 399 void G4LogicalVolume::ResetMass() 400 { 400 { 401 G4MT_mass= 0.0; 401 G4MT_mass= 0.0; 402 } 402 } 403 403 404 // ******************************************* 404 // ******************************************************************** 405 // GetSolid 405 // GetSolid 406 // ******************************************* 406 // ******************************************************************** 407 // 407 // 408 G4VSolid* G4LogicalVolume::GetSolid(G4LVData & 408 G4VSolid* G4LogicalVolume::GetSolid(G4LVData &instLVdata) // const 409 { 409 { 410 return instLVdata.fSolid; 410 return instLVdata.fSolid; 411 } 411 } 412 412 413 G4VSolid* G4LogicalVolume::GetSolid() const 413 G4VSolid* G4LogicalVolume::GetSolid() const 414 { 414 { 415 return this->GetSolid( subInstanceManager.of 415 return this->GetSolid( subInstanceManager.offset[instanceID] ); 416 } 416 } 417 417 418 // ******************************************* 418 // ******************************************************************** 419 // SetSolid 419 // SetSolid 420 // ******************************************* 420 // ******************************************************************** 421 // 421 // 422 void G4LogicalVolume::SetSolid(G4VSolid *pSoli 422 void G4LogicalVolume::SetSolid(G4VSolid *pSolid) 423 { 423 { 424 424 425 G4MT_solid = pSolid; 425 G4MT_solid = pSolid; 426 this->ResetMass(); 426 this->ResetMass(); 427 } 427 } 428 428 429 void G4LogicalVolume::SetSolid(G4LVData& instL 429 void G4LogicalVolume::SetSolid(G4LVData& instLVdata, G4VSolid* pSolid) 430 { 430 { 431 instLVdata.fSolid = pSolid; 431 instLVdata.fSolid = pSolid; 432 instLVdata.fMass = 0.0; 432 instLVdata.fMass = 0.0; 433 } 433 } 434 434 435 // ******************************************* 435 // ******************************************************************** 436 // GetMaterial 436 // GetMaterial 437 // ******************************************* 437 // ******************************************************************** 438 // 438 // 439 G4Material* G4LogicalVolume::GetMaterial() con 439 G4Material* G4LogicalVolume::GetMaterial() const 440 { 440 { 441 return G4MT_material; 441 return G4MT_material; 442 } 442 } 443 443 444 // ******************************************* 444 // ******************************************************************** 445 // SetMaterial 445 // SetMaterial 446 // ******************************************* 446 // ******************************************************************** 447 // 447 // 448 void G4LogicalVolume::SetMaterial(G4Material* 448 void G4LogicalVolume::SetMaterial(G4Material* pMaterial) 449 { 449 { 450 G4MT_material = pMaterial; 450 G4MT_material = pMaterial; 451 G4MT_mass = 0.0; 451 G4MT_mass = 0.0; 452 } 452 } 453 453 454 // ******************************************* 454 // ******************************************************************** 455 // UpdateMaterial 455 // UpdateMaterial 456 // ******************************************* 456 // ******************************************************************** 457 // 457 // 458 void G4LogicalVolume::UpdateMaterial(G4Materia 458 void G4LogicalVolume::UpdateMaterial(G4Material* pMaterial) 459 { 459 { 460 G4MT_material=pMaterial; 460 G4MT_material=pMaterial; 461 if (fRegion != nullptr) { G4MT_ccouple = fRe 461 if (fRegion != nullptr) { G4MT_ccouple = fRegion->FindCouple(pMaterial); } 462 G4MT_mass = 0.0; 462 G4MT_mass = 0.0; 463 } 463 } 464 464 465 // ******************************************* 465 // ******************************************************************** 466 // GetSensitiveDetector 466 // GetSensitiveDetector 467 // ******************************************* 467 // ******************************************************************** 468 // 468 // 469 G4VSensitiveDetector* G4LogicalVolume::GetSens 469 G4VSensitiveDetector* G4LogicalVolume::GetSensitiveDetector() const 470 { 470 { 471 return G4MT_sdetector; 471 return G4MT_sdetector; 472 } 472 } 473 473 474 // ******************************************* 474 // ******************************************************************** 475 // SetSensitiveDetector 475 // SetSensitiveDetector 476 // ******************************************* 476 // ******************************************************************** 477 // 477 // 478 void G4LogicalVolume::SetSensitiveDetector(G4V 478 void G4LogicalVolume::SetSensitiveDetector(G4VSensitiveDetector* pSDetector) 479 { 479 { 480 G4MT_sdetector = pSDetector; 480 G4MT_sdetector = pSDetector; 481 if (G4Threading::IsMasterThread()) { fSensi 481 if (G4Threading::IsMasterThread()) { fSensitiveDetector = pSDetector; } 482 } 482 } 483 483 484 // ******************************************* 484 // ******************************************************************** 485 // GetMaterialCutsCouple 485 // GetMaterialCutsCouple 486 // ******************************************* 486 // ******************************************************************** 487 // 487 // 488 const G4MaterialCutsCouple* G4LogicalVolume::G 488 const G4MaterialCutsCouple* G4LogicalVolume::GetMaterialCutsCouple() const 489 { 489 { 490 return G4MT_ccouple; 490 return G4MT_ccouple; 491 } 491 } 492 492 493 // ******************************************* 493 // ******************************************************************** 494 // SetMaterialCutsCouple 494 // SetMaterialCutsCouple 495 // ******************************************* 495 // ******************************************************************** 496 // 496 // 497 void G4LogicalVolume::SetMaterialCutsCouple(G4 497 void G4LogicalVolume::SetMaterialCutsCouple(G4MaterialCutsCouple* cuts) 498 { 498 { 499 G4MT_ccouple = cuts; 499 G4MT_ccouple = cuts; 500 } 500 } 501 501 502 // ******************************************* 502 // ******************************************************************** 503 // IsAncestor 503 // IsAncestor 504 // 504 // 505 // Finds out if the current logical volume is 505 // Finds out if the current logical volume is an ancestor of a given 506 // physical volume 506 // physical volume 507 // ******************************************* 507 // ******************************************************************** 508 // 508 // 509 G4bool 509 G4bool 510 G4LogicalVolume::IsAncestor(const G4VPhysicalV 510 G4LogicalVolume::IsAncestor(const G4VPhysicalVolume* aVolume) const 511 { 511 { 512 G4bool isDaughter = IsDaughter(aVolume); 512 G4bool isDaughter = IsDaughter(aVolume); 513 if (!isDaughter) 513 if (!isDaughter) 514 { 514 { 515 for (auto itDau = fDaughters.cbegin(); itD 515 for (auto itDau = fDaughters.cbegin(); itDau != fDaughters.cend(); ++itDau) 516 { 516 { 517 isDaughter = (*itDau)->GetLogicalVolume( 517 isDaughter = (*itDau)->GetLogicalVolume()->IsAncestor(aVolume); 518 if (isDaughter) break; 518 if (isDaughter) break; 519 } 519 } 520 } 520 } 521 return isDaughter; 521 return isDaughter; 522 } 522 } 523 523 524 // ******************************************* 524 // ******************************************************************** 525 // TotalVolumeEntities 525 // TotalVolumeEntities 526 // 526 // 527 // Returns the total number of physical volume 527 // Returns the total number of physical volumes (replicated or placed) 528 // in the tree represented by the current logi 528 // in the tree represented by the current logical volume. 529 // ******************************************* 529 // ******************************************************************** 530 // 530 // 531 G4int G4LogicalVolume::TotalVolumeEntities() c 531 G4int G4LogicalVolume::TotalVolumeEntities() const 532 { 532 { 533 G4int vols = 1; 533 G4int vols = 1; 534 for (auto itDau = fDaughters.cbegin(); itDau 534 for (auto itDau = fDaughters.cbegin(); itDau != fDaughters.cend(); ++itDau) 535 { 535 { 536 G4VPhysicalVolume* physDaughter = (*itDau) 536 G4VPhysicalVolume* physDaughter = (*itDau); 537 vols += physDaughter->GetMultiplicity() 537 vols += physDaughter->GetMultiplicity() 538 *physDaughter->GetLogicalVolume()-> 538 *physDaughter->GetLogicalVolume()->TotalVolumeEntities(); 539 } 539 } 540 return vols; 540 return vols; 541 } 541 } 542 542 543 // ******************************************* 543 // ******************************************************************** 544 // GetMass 544 // GetMass 545 // 545 // 546 // Returns the mass of the logical volume tree 546 // Returns the mass of the logical volume tree computed from the 547 // estimated geometrical volume of each solid 547 // estimated geometrical volume of each solid and material associated 548 // to the logical volume and its daughters. 548 // to the logical volume and its daughters. 549 // NOTE: the computation may require considera 549 // NOTE: the computation may require considerable amount of time, 550 // depending from the complexity of the 550 // depending from the complexity of the geometry tree. 551 // The returned value is cached and can 551 // The returned value is cached and can be used for successive 552 // calls (default), unless recomputation 552 // calls (default), unless recomputation is forced by providing 553 // 'true' for the boolean argument in in 553 // 'true' for the boolean argument in input. Computation should 554 // be forced if the geometry setup has c 554 // be forced if the geometry setup has changed after the previous 555 // call. By setting the 'propagate' bool 555 // call. By setting the 'propagate' boolean flag to 'false' the 556 // method returns the mass of the presen 556 // method returns the mass of the present logical volume only 557 // (subtracted for the volume occupied b 557 // (subtracted for the volume occupied by the daughter volumes). 558 // The extra argument 'parMaterial' is i 558 // The extra argument 'parMaterial' is internally used to 559 // consider cases of geometrical paramet 559 // consider cases of geometrical parameterisations by material. 560 // ******************************************* 560 // ******************************************************************** 561 // 561 // 562 G4double G4LogicalVolume::GetMass(G4bool force 562 G4double G4LogicalVolume::GetMass(G4bool forced, 563 G4bool propa 563 G4bool propagate, 564 G4Material* 564 G4Material* parMaterial) 565 { 565 { 566 // Return the cached non-zero value, if not 566 // Return the cached non-zero value, if not forced 567 // 567 // 568 if ( ((G4MT_mass) != 0.0) && (!forced) ) { 568 if ( ((G4MT_mass) != 0.0) && (!forced) ) { return G4MT_mass; } 569 569 570 // Global density and computed mass associat 570 // Global density and computed mass associated to the logical 571 // volume without considering its daughters 571 // volume without considering its daughters 572 // 572 // 573 G4Material* logMaterial = parMaterial != nul 573 G4Material* logMaterial = parMaterial != nullptr ? parMaterial : GetMaterial(); 574 if (logMaterial == nullptr) 574 if (logMaterial == nullptr) 575 { 575 { 576 std::ostringstream message; 576 std::ostringstream message; 577 message << "No material associated to the 577 message << "No material associated to the logical volume: " 578 << fName << " !" << G4endl 578 << fName << " !" << G4endl 579 << "Sorry, cannot compute the mass 579 << "Sorry, cannot compute the mass ..."; 580 G4Exception("G4LogicalVolume::GetMass()", 580 G4Exception("G4LogicalVolume::GetMass()", "GeomMgt0002", 581 FatalException, message); 581 FatalException, message); 582 return 0.0; 582 return 0.0; 583 } 583 } 584 if ( GetSolid() == nullptr ) 584 if ( GetSolid() == nullptr ) 585 { 585 { 586 std::ostringstream message; 586 std::ostringstream message; 587 message << "No solid is associated to the 587 message << "No solid is associated to the logical volume: " 588 << fName << " !" << G4endl 588 << fName << " !" << G4endl 589 << "Sorry, cannot compute the mass 589 << "Sorry, cannot compute the mass ..."; 590 G4Exception("G4LogicalVolume::GetMass()", 590 G4Exception("G4LogicalVolume::GetMass()", "GeomMgt0002", 591 FatalException, message); 591 FatalException, message); 592 return 0.0; 592 return 0.0; 593 } 593 } 594 G4double globalDensity = logMaterial->GetDen 594 G4double globalDensity = logMaterial->GetDensity(); 595 G4double motherMass = GetSolid()->GetCubicVo 595 G4double motherMass = GetSolid()->GetCubicVolume() * globalDensity; 596 G4double massSum = motherMass; 596 G4double massSum = motherMass; 597 597 598 // For each daughter in the tree, subtract t 598 // For each daughter in the tree, subtract the mass occupied 599 // and if required by the propagate flag, ad 599 // and if required by the propagate flag, add the real daughter's 600 // one computed recursively 600 // one computed recursively 601 601 602 for (auto itDau = fDaughters.cbegin(); itDau 602 for (auto itDau = fDaughters.cbegin(); itDau != fDaughters.cend(); ++itDau) 603 { 603 { 604 G4VPhysicalVolume* physDaughter = (*itDau) 604 G4VPhysicalVolume* physDaughter = (*itDau); 605 G4LogicalVolume* logDaughter = physDaughte 605 G4LogicalVolume* logDaughter = physDaughter->GetLogicalVolume(); 606 G4double subMass = 0.0; 606 G4double subMass = 0.0; 607 G4VSolid* daughterSolid = nullptr; 607 G4VSolid* daughterSolid = nullptr; 608 G4Material* daughterMaterial = nullptr; 608 G4Material* daughterMaterial = nullptr; 609 609 610 // Compute the mass to subtract and to add 610 // Compute the mass to subtract and to add for each daughter 611 // considering its multiplicity (i.e. repl 611 // considering its multiplicity (i.e. replicated or not) and 612 // eventually its parameterisation (by sol 612 // eventually its parameterisation (by solid and/or by material) 613 // 613 // 614 for (auto i=0; i<physDaughter->GetMultipli 614 for (auto i=0; i<physDaughter->GetMultiplicity(); ++i) 615 { 615 { 616 G4VPVParameterisation* physParam = physD 616 G4VPVParameterisation* physParam = physDaughter->GetParameterisation(); 617 if (physParam != nullptr) 617 if (physParam != nullptr) 618 { 618 { 619 daughterSolid = physParam->ComputeSoli 619 daughterSolid = physParam->ComputeSolid(i, physDaughter); 620 daughterSolid->ComputeDimensions(physP 620 daughterSolid->ComputeDimensions(physParam, i, physDaughter); 621 daughterMaterial = physParam->ComputeM 621 daughterMaterial = physParam->ComputeMaterial(i, physDaughter); 622 } 622 } 623 else 623 else 624 { 624 { 625 daughterSolid = logDaughter->GetSolid( 625 daughterSolid = logDaughter->GetSolid(); 626 daughterMaterial = logDaughter->GetMat 626 daughterMaterial = logDaughter->GetMaterial(); 627 } 627 } 628 subMass = daughterSolid->GetCubicVolume( 628 subMass = daughterSolid->GetCubicVolume() * globalDensity; 629 629 630 // Subtract the daughter's portion for t 630 // Subtract the daughter's portion for the mass and, if required, 631 // add the real daughter's mass computed 631 // add the real daughter's mass computed recursively 632 // 632 // 633 massSum -= subMass; 633 massSum -= subMass; 634 if (propagate) 634 if (propagate) 635 { 635 { 636 massSum += logDaughter->GetMass(true, 636 massSum += logDaughter->GetMass(true, true, daughterMaterial); 637 } 637 } 638 } 638 } 639 } 639 } 640 G4MT_mass = massSum; 640 G4MT_mass = massSum; 641 return massSum; 641 return massSum; 642 } 642 } 643 643 644 // ******************************************* 644 // ******************************************************************** 645 // Change the daughters volume type -- checkin 645 // Change the daughters volume type -- checking proposed values 646 // 646 // 647 // Undertakes primitive checking, to ensure t 647 // Undertakes primitive checking, to ensure that only 'legal' changes 648 // are made: 648 // are made: 649 // - any type to 'external' ( user respons 649 // - any type to 'external' ( user responsibility ) 650 // - the type proposed is checked against t 650 // - the type proposed is checked against the deduced type 651 // (for potential switch back to 'intern 651 // (for potential switch back to 'internal' type.) 652 // Returns success (true) or failure (false) 652 // Returns success (true) or failure (false) 653 // 653 // 654 G4bool G4LogicalVolume::ChangeDaughtersType(EV 654 G4bool G4LogicalVolume::ChangeDaughtersType(EVolume aType) 655 { 655 { 656 G4bool works = false; 656 G4bool works = false; 657 if( aType == kExternal ) 657 if( aType == kExternal ) 658 { 658 { 659 // It is the responsibility of External Na 659 // It is the responsibility of External Navigator to handle types selected 660 // 660 // 661 fDaughtersVolumeType = aType; 661 fDaughtersVolumeType = aType; 662 works = true; 662 works = true; 663 } 663 } 664 else 664 else 665 { 665 { 666 EVolume expectedVType = DeduceDaughtersTyp 666 EVolume expectedVType = DeduceDaughtersType(); 667 works = (expectedVType == aType); 667 works = (expectedVType == aType); 668 if ( works ) 668 if ( works ) 669 { 669 { 670 fDaughtersVolumeType = aType; 670 fDaughtersVolumeType = aType; 671 } 671 } 672 } 672 } 673 return works; 673 return works; 674 } 674 } 675 675 676 // ******************************************* 676 // ******************************************************************** 677 // SetVisAttributes - copy version 677 // SetVisAttributes - copy version 678 // ******************************************* 678 // ******************************************************************** 679 // 679 // 680 void G4LogicalVolume::SetVisAttributes (const 680 void G4LogicalVolume::SetVisAttributes (const G4VisAttributes& VA) 681 { 681 { 682 if (G4Threading::IsWorkerThread()) return; 682 if (G4Threading::IsWorkerThread()) return; 683 fVisAttributes = std::make_shared<const G4Vi 683 fVisAttributes = std::make_shared<const G4VisAttributes>(VA); 684 } 684 } 685 685 686 // ******************************************* 686 // ******************************************************************** 687 // SetVisAttributes 687 // SetVisAttributes 688 // ******************************************* 688 // ******************************************************************** 689 // 689 // 690 void G4LogicalVolume::SetVisAttributes (const 690 void G4LogicalVolume::SetVisAttributes (const G4VisAttributes* pVA) 691 { 691 { 692 if (G4Threading::IsWorkerThread()) return; 692 if (G4Threading::IsWorkerThread()) return; 693 fVisAttributes = std::shared_ptr<const G4Vis 693 fVisAttributes = std::shared_ptr<const G4VisAttributes>(pVA,[](const G4VisAttributes*){}); 694 } 694 } 695 695