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