Geant4 Cross Reference |
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 // G4Region class implementation 27 // 28 // 18.09.02, G.Cosmo - Initial version 29 // -------------------------------------------------------------------- 30 31 #include "G4Region.hh" 32 #include "G4RegionStore.hh" 33 #include "G4LogicalVolume.hh" 34 #include "G4VPhysicalVolume.hh" 35 #include "G4LogicalVolumeStore.hh" 36 #include "G4VNestedParameterisation.hh" 37 #include "G4VUserRegionInformation.hh" 38 #include "G4Material.hh" 39 40 // These macros changes the references to fields that are now encapsulated 41 // in the class G4RegionData. 42 // 43 #define G4MT_fsmanager ((subInstanceManager.offset[instanceID]).fFastSimulationManager) 44 #define G4MT_rsaction ((subInstanceManager.offset[instanceID]).fRegionalSteppingAction) 45 46 // This new field helps to use the class G4RegionManager 47 // 48 G4RegionManager G4Region::subInstanceManager; 49 50 // ******************************************************************* 51 // GetSubInstanceManager: 52 // - Returns the private data instance manager. 53 // ******************************************************************* 54 // 55 const G4RegionManager& G4Region::GetSubInstanceManager() 56 { 57 return subInstanceManager; 58 } 59 60 // ******************************************************************* 61 // Constructor: 62 // - Adds self to region Store 63 // ******************************************************************* 64 // 65 G4Region::G4Region(const G4String& pName) 66 : fName(pName) 67 { 68 69 instanceID = subInstanceManager.CreateSubInstance(); 70 G4MT_fsmanager = nullptr; 71 G4MT_rsaction = nullptr; 72 73 G4RegionStore* rStore = G4RegionStore::GetInstance(); 74 if (rStore->GetRegion(pName, false) != nullptr) 75 { 76 std::ostringstream message; 77 message << "The region has NOT been registered !" << G4endl 78 << " Region " << pName << " already existing in store !" 79 << G4endl; 80 G4Exception("G4Region::G4Region()", "GeomMgt1001", 81 JustWarning, message); 82 } 83 else 84 { 85 rStore->Register(this); 86 } 87 } 88 89 // ******************************************************************** 90 // Fake default constructor - sets only member data and allocates memory 91 // for usage restricted to object persistency. 92 // ******************************************************************** 93 // 94 G4Region::G4Region( __void__& ) 95 : fName("") 96 { 97 instanceID = subInstanceManager.CreateSubInstance(); 98 G4MT_fsmanager = nullptr; 99 G4MT_rsaction = nullptr; 100 101 // Register to store 102 // 103 G4RegionStore::GetInstance()->Register(this); 104 } 105 106 // ******************************************************************* 107 // Destructor: 108 // - Removes self from region Store 109 // ******************************************************************* 110 // 111 G4Region::~G4Region() 112 { 113 G4RegionStore::GetInstance()->DeRegister(this); 114 delete fUserInfo; 115 } 116 117 // ******************************************************************** 118 // SetName - Set region name and notify store of the change 119 // ******************************************************************** 120 // 121 void G4Region::SetName(const G4String& pName) 122 { 123 fName = pName; 124 G4RegionStore::GetInstance()->SetMapValid(false); 125 } 126 127 // ******************************************************************** 128 // SetFastSimulationManager 129 // ******************************************************************** 130 // 131 void G4Region::SetFastSimulationManager(G4FastSimulationManager* fsm) 132 { 133 G4MT_fsmanager = fsm; 134 } 135 136 // ******************************************************************** 137 // GetFastSimulationManager 138 // ******************************************************************** 139 // 140 G4FastSimulationManager* G4Region::GetFastSimulationManager() const 141 { 142 return G4MT_fsmanager; 143 } 144 145 // ******************************************************************** 146 // SetRegionalSteppingAction 147 // ******************************************************************** 148 // 149 void G4Region::SetRegionalSteppingAction(G4UserSteppingAction* rusa) 150 { 151 G4MT_rsaction = rusa; 152 } 153 154 // ******************************************************************** 155 // GetRegionalSteppingAction 156 // ******************************************************************** 157 // 158 G4UserSteppingAction* G4Region::GetRegionalSteppingAction() const 159 { 160 return G4MT_rsaction; 161 } 162 163 // ******************************************************************* 164 // ScanVolumeTree: 165 // - Scans recursively the 'lv' logical volume tree, retrieves 166 // and places all materials in the list. 167 // - The boolean flag 'region' identifies if the volume tree must 168 // have region reset (false) or if the current region must be 169 // associated to the logical volume 'lv' and its tree (true). 170 // ******************************************************************* 171 // 172 void G4Region::ScanVolumeTree(G4LogicalVolume* lv, G4bool region) 173 { 174 // If logical volume is going to become a region, add 175 // its material to the list if not already present 176 // 177 G4Region* currentRegion = nullptr; 178 std::size_t noDaughters = lv->GetNoDaughters(); 179 G4Material* volMat = lv->GetMaterial(); 180 if((volMat == nullptr) && fInMassGeometry) 181 { 182 std::ostringstream message; 183 message << "Logical volume <" << lv->GetName() << ">" << G4endl 184 << "does not have a valid material pointer." << G4endl 185 << "A logical volume belonging to the (tracking) world volume " 186 << "must have a valid material."; 187 G4Exception("G4Region::ScanVolumeTree()", "GeomMgt0002", 188 FatalException, message, "Check your geometry construction."); 189 } 190 if (region) 191 { 192 currentRegion = this; 193 if (volMat != nullptr) 194 { 195 AddMaterial(volMat); 196 auto baseMat = const_cast<G4Material*>(volMat->GetBaseMaterial()); 197 if (baseMat != nullptr) { AddMaterial(baseMat); } 198 } 199 } 200 201 // Set the LV region to be either the current region or NULL, 202 // according to the boolean selector 203 // 204 lv->SetRegion(currentRegion); 205 206 // Stop recursion here if no further daughters are involved 207 // 208 if(noDaughters==0) return; 209 210 G4VPhysicalVolume* daughterPVol = lv->GetDaughter(0); 211 if (daughterPVol->IsParameterised()) 212 { 213 // Adopt special treatment in case of parameterised volumes, 214 // where parameterisation involves a new material scan 215 // 216 G4VPVParameterisation* pParam = daughterPVol->GetParameterisation(); 217 218 if (pParam->GetMaterialScanner() != nullptr) 219 { 220 std::size_t matNo = pParam->GetMaterialScanner()->GetNumberOfMaterials(); 221 for (std::size_t mat=0; mat<matNo; ++mat) 222 { 223 volMat = pParam->GetMaterialScanner()->GetMaterial((G4int)mat); 224 if((volMat == nullptr) && fInMassGeometry) 225 { 226 std::ostringstream message; 227 message << "The parameterisation for the physical volume <" 228 << daughterPVol->GetName() << ">" << G4endl 229 << "does not return a valid material pointer." << G4endl 230 << "A volume belonging to the (tracking) world volume must " 231 << "have a valid material."; 232 G4Exception("G4Region::ScanVolumeTree()", "GeomMgt0002", 233 FatalException, message, "Check your parameterisation."); 234 } 235 if (volMat != nullptr) 236 { 237 AddMaterial(volMat); 238 auto baseMat = const_cast<G4Material*>(volMat->GetBaseMaterial()); 239 if (baseMat != nullptr) { AddMaterial(baseMat); } 240 } 241 } 242 } 243 else 244 { 245 std::size_t repNo = daughterPVol->GetMultiplicity(); 246 for (std::size_t rep=0; rep<repNo; ++rep) 247 { 248 volMat = pParam->ComputeMaterial((G4int)rep, daughterPVol); 249 if((volMat == nullptr) && fInMassGeometry) 250 { 251 std::ostringstream message; 252 message << "The parameterisation for the physical volume <" 253 << daughterPVol->GetName() << ">" << G4endl 254 << "does not return a valid material pointer." << G4endl 255 << "A volume belonging to the (tracking) world volume must " 256 << "have a valid material."; 257 G4Exception("G4Region::ScanVolumeTree()", "GeomMgt0002", 258 FatalException, message, "Check your parameterisation."); 259 } 260 if(volMat != nullptr) 261 { 262 AddMaterial(volMat); 263 auto baseMat = const_cast<G4Material*>(volMat->GetBaseMaterial()); 264 if (baseMat != nullptr) { AddMaterial(baseMat); } 265 } 266 } 267 } 268 G4LogicalVolume* daughterLVol = daughterPVol->GetLogicalVolume(); 269 ScanVolumeTree(daughterLVol, region); 270 } 271 else 272 { 273 for (std::size_t i=0; i<noDaughters; ++i) 274 { 275 G4LogicalVolume* daughterLVol = lv->GetDaughter(i)->GetLogicalVolume(); 276 if (!daughterLVol->IsRootRegion()) 277 { 278 // Set daughter's LV to be a region and store materials in 279 // the materials list, if the LV is not already a root region 280 // 281 ScanVolumeTree(daughterLVol, region); 282 } 283 } 284 } 285 } 286 287 // ******************************************************************* 288 // AddRootLogicalVolume: 289 // - Adds a root logical volume and sets its daughters flags as 290 // regions. It also recomputes the materials list for the region. 291 // ******************************************************************* 292 // 293 void G4Region::AddRootLogicalVolume(G4LogicalVolume* lv, G4bool search) 294 { 295 // Check if logical volume is already belonging to another region 296 // 297 if ((lv->IsRootRegion()) && (lv->GetRegion() != this)) 298 { 299 std::ostringstream message; 300 message << "Logical volume <" << lv->GetName() << "> is already set as" << G4endl 301 << "root for region <" << lv->GetRegion()->GetName() << ">." << G4endl 302 << "It cannot be root logical volume for another region <" << GetName() 303 << ">" << G4endl; 304 G4Exception("G4Region::AddRootLogicalVolume()", "GeomMgt0002", FatalException, 305 message, "A logical volume cannot belong to more than one region!"); 306 return; 307 } 308 309 // Check the logical volume is not already in the list 310 // 311 if (search) 312 { 313 auto pos = std::find(fRootVolumes.cbegin(),fRootVolumes.cend(),lv); 314 if (pos == fRootVolumes.cend()) 315 { 316 // Insert the root volume in the list and set it as root region 317 // 318 fRootVolumes.push_back(lv); 319 lv->SetRegionRootFlag(true); 320 } 321 } 322 else // WARNING: user *MUST* guarantee lv is not already inserted. 323 { // Providing speedup for very complex flat geometries 324 fRootVolumes.push_back(lv); 325 lv->SetRegionRootFlag(true); 326 } 327 // Scan recursively the tree of daugther volumes and set regions 328 // 329 ScanVolumeTree(lv, true); 330 331 // Set region as modified 332 // 333 fRegionMod = true; 334 } 335 336 // ******************************************************************* 337 // RemoveRootLogicalVolume: 338 // - Removes a root logical volume and resets its daughters flags as 339 // regions. It also recomputes the materials list for the region. 340 // ******************************************************************* 341 // 342 void G4Region::RemoveRootLogicalVolume(G4LogicalVolume* lv, G4bool scan) 343 { 344 // Find and remove logical volume from the list 345 // 346 auto pos = std::find(fRootVolumes.cbegin(),fRootVolumes.cend(),lv); 347 if (pos != fRootVolumes.cend()) 348 { 349 if (fRootVolumes.size() != 1) // Avoid resetting flag for world since 350 { // volume may be already deleted ! 351 lv->SetRegionRootFlag(false); 352 } 353 fRootVolumes.erase(pos); 354 } 355 356 if (scan) // Update the materials list 357 { 358 UpdateMaterialList(); 359 } 360 361 // Set region as modified 362 // 363 fRegionMod = true; 364 } 365 366 // ******************************************************************** 367 // Clean 368 // ******************************************************************** 369 // 370 void G4Region::Clean() 371 { 372 subInstanceManager.FreeSlave(); 373 } 374 375 // ******************************************************************* 376 // ClearMaterialList: 377 // - Clears the material list. 378 // ******************************************************************* 379 // 380 void G4Region::ClearMaterialList() 381 { 382 fMaterials.clear(); 383 } 384 385 // ******************************************************************* 386 // UpdateMaterialList: 387 // - computes material list looping through 388 // each root logical volume in the region. 389 // ******************************************************************* 390 // 391 void G4Region::UpdateMaterialList() 392 { 393 // Reset the materials list 394 // 395 ClearMaterialList(); 396 397 // Loop over the root logical volumes and rebuild the list 398 // of materials from scratch 399 // 400 for (auto pLV=fRootVolumes.cbegin(); pLV!=fRootVolumes.cend(); ++pLV) 401 { 402 ScanVolumeTree(*pLV, true); 403 } 404 } 405 406 // ******************************************************************* 407 // SetWorld: 408 // - Set the world physical volume if this region belongs to this 409 // world. If the given pointer is null, reset the pointer. 410 // ******************************************************************* 411 // 412 void G4Region::SetWorld(G4VPhysicalVolume* wp) 413 { 414 if(wp == nullptr) 415 { fWorldPhys = nullptr; } 416 else 417 { if(BelongsTo(wp)) fWorldPhys = wp; } 418 419 return; 420 } 421 422 // ******************************************************************* 423 // BelongsTo: 424 // - Returns whether this region belongs to the given physical volume 425 // (recursively scanned to the bottom of the hierarchy) 426 // ******************************************************************* 427 // 428 G4bool G4Region::BelongsTo(G4VPhysicalVolume* thePhys) const 429 { 430 G4LogicalVolume* currLog = thePhys->GetLogicalVolume(); 431 if (currLog->GetRegion()==this) {return true;} 432 433 std::size_t nDaughters = currLog->GetNoDaughters(); 434 while ((nDaughters--) != 0) // Loop checking, 06.08.2015, G.Cosmo 435 { 436 if (BelongsTo(currLog->GetDaughter(nDaughters))) {return true;} 437 } 438 439 return false; 440 } 441 442 // ******************************************************************* 443 // ClearFastSimulationManager: 444 // - Set G4FastSimulationManager pointer to the one for the parent region 445 // if it exists. Otherwise set to null. 446 // ******************************************************************* 447 // 448 void G4Region::ClearFastSimulationManager() 449 { 450 G4bool isUnique; 451 G4Region* parent = GetParentRegion(isUnique); 452 if(parent != nullptr) 453 { 454 if (isUnique) 455 { 456 G4MT_fsmanager = parent->GetFastSimulationManager(); 457 } 458 else 459 { 460 std::ostringstream message; 461 message << "Region <" << fName << "> belongs to more than" 462 << " one parent region !" << G4endl 463 << "A region cannot belong to more than one direct parent region," 464 << G4endl 465 << "to have fast-simulation assigned."; 466 G4Exception("G4Region::ClearFastSimulationManager()", 467 "GeomMgt1002", JustWarning, message); 468 G4MT_fsmanager = nullptr; 469 } 470 } 471 else 472 { 473 G4MT_fsmanager = nullptr; 474 } 475 } 476 477 // ******************************************************************* 478 // GetParentRegion: 479 // - Returns a region that contains this region. 480 // Otherwise null is returned. 481 // ******************************************************************* 482 // 483 G4Region* G4Region::GetParentRegion(G4bool& unique) const 484 { 485 G4Region* parent = nullptr; unique = true; 486 G4LogicalVolumeStore* lvStore = G4LogicalVolumeStore::GetInstance(); 487 488 // Loop over all logical volumes in the store 489 // 490 for(auto lvItr=lvStore->cbegin(); lvItr!=lvStore->cend(); ++lvItr) 491 { 492 std::size_t nD = (*lvItr)->GetNoDaughters(); 493 G4Region* aR = (*lvItr)->GetRegion(); 494 495 // Loop over all daughters of each logical volume 496 // 497 for(std::size_t iD=0; iD<nD; ++iD) 498 { 499 if((*lvItr)->GetDaughter(iD)->GetLogicalVolume()->GetRegion()==this) 500 { 501 if(parent != nullptr) 502 { 503 if(parent!=aR) { unique = false; } 504 } 505 else // Cache LV parent region which includes a daughter volume 506 // with the same associated region as the current one 507 { 508 parent = aR; 509 } 510 } 511 } 512 } 513 return parent; 514 } 515