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