Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 // class G4PVReplica Implementation 26 // class G4PVReplica Implementation 27 // 27 // 28 // 29.07.95, P.Kent - First non-stub version 28 // 29.07.95, P.Kent - First non-stub version 29 // ------------------------------------------- 29 // ---------------------------------------------------------------------- 30 30 31 #include "G4PVReplica.hh" 31 #include "G4PVReplica.hh" 32 #include "G4LogicalVolume.hh" 32 #include "G4LogicalVolume.hh" 33 33 34 // ------------------------------------------- << 35 G4PVRManager G4PVReplica::subInstanceManager; 34 G4PVRManager G4PVReplica::subInstanceManager; 36 // Helping in the use of the class G4PVRMana 35 // Helping in the use of the class G4PVRManager. 37 36 38 #define G4MT_copyNo ((subInstanceManager.offse << 39 // This macro changes the references to fiel << 40 // in the class G4ReplicaData. << 41 << 42 // ------------------------------------------- << 43 G4PVReplica::G4PVReplica( const G4String& pNam 37 G4PVReplica::G4PVReplica( const G4String& pName, 44 G4LogicalVolum 38 G4LogicalVolume* pLogical, 45 G4VPhysicalVol 39 G4VPhysicalVolume* pMother, 46 const EAxis pAxis, 40 const EAxis pAxis, 47 const G4int nReplica 41 const G4int nReplicas, 48 const G4double width 42 const G4double width, 49 const G4double offse 43 const G4double offset ) 50 : G4VPhysicalVolume(nullptr, G4ThreeVector() 44 : G4VPhysicalVolume(nullptr, G4ThreeVector(), pName, pLogical, pMother) 51 { 45 { 52 46 53 instanceID = subInstanceManager.CreateSubIns 47 instanceID = subInstanceManager.CreateSubInstance(); 54 48 >> 49 G4MT_copyNo = -1; >> 50 55 if ((pMother == nullptr) || (pMother->GetLog 51 if ((pMother == nullptr) || (pMother->GetLogicalVolume() == nullptr)) 56 { 52 { 57 std::ostringstream message; 53 std::ostringstream message; 58 message << "NULL pointer specified as moth 54 message << "NULL pointer specified as mother volume." << G4endl 59 << "The world volume cannot be sli 55 << "The world volume cannot be sliced or parameterised !"; 60 G4Exception("G4PVReplica::G4PVReplica()", 56 G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002", 61 FatalException, message); 57 FatalException, message); 62 return; 58 return; 63 } 59 } 64 G4LogicalVolume* motherLogical = pMother->Ge 60 G4LogicalVolume* motherLogical = pMother->GetLogicalVolume(); 65 if (pLogical == motherLogical) 61 if (pLogical == motherLogical) 66 { 62 { 67 G4Exception("G4PVReplica::G4PVReplica()", 63 G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002", 68 FatalException, "Cannot place 64 FatalException, "Cannot place a volume inside itself!"); 69 return; 65 return; 70 } 66 } 71 SetMotherLogical(motherLogical); 67 SetMotherLogical(motherLogical); 72 motherLogical->AddDaughter(this); 68 motherLogical->AddDaughter(this); 73 if (motherLogical->GetNoDaughters() != 1) 69 if (motherLogical->GetNoDaughters() != 1) 74 { 70 { 75 std::ostringstream message; 71 std::ostringstream message; 76 message << "Replica or parameterised volum 72 message << "Replica or parameterised volume must be the only daughter !" 77 << G4endl 73 << G4endl 78 << " Mother physical volume: " 74 << " Mother physical volume: " << pMother->GetName() << G4endl 79 << " Replicated volume: " << p 75 << " Replicated volume: " << pName; 80 G4Exception("G4PVReplica::G4PVReplica()", 76 G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002", 81 FatalException, message); 77 FatalException, message); 82 return; 78 return; 83 } 79 } 84 CheckAndSetParameters (pAxis, nReplicas, wid 80 CheckAndSetParameters (pAxis, nReplicas, width, offset); 85 } 81 } 86 82 87 // ------------------------------------------- << 88 G4PVReplica::G4PVReplica( const G4String& pNam 83 G4PVReplica::G4PVReplica( const G4String& pName, 89 G4LogicalVolum 84 G4LogicalVolume* pLogical, 90 G4LogicalVolum 85 G4LogicalVolume* pMotherLogical, 91 const EAxis pAxis, 86 const EAxis pAxis, 92 const G4int nReplica 87 const G4int nReplicas, 93 const G4double width 88 const G4double width, 94 const G4double offse 89 const G4double offset ) 95 : G4VPhysicalVolume(nullptr, G4ThreeVector() 90 : G4VPhysicalVolume(nullptr, G4ThreeVector(), pName, pLogical, nullptr) 96 { 91 { 97 92 98 instanceID = subInstanceManager.CreateSubIns 93 instanceID = subInstanceManager.CreateSubInstance(); >> 94 G4MT_copyNo = -1; 99 95 100 if (pMotherLogical == nullptr) 96 if (pMotherLogical == nullptr) 101 { 97 { 102 std::ostringstream message; 98 std::ostringstream message; 103 message << "NULL pointer specified as moth 99 message << "NULL pointer specified as mother volume for " 104 << pName << "."; 100 << pName << "."; 105 G4Exception("G4PVReplica::G4PVReplica()", 101 G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002", 106 FatalException, message); 102 FatalException, message); 107 return; 103 return; 108 } 104 } 109 if (pLogical == pMotherLogical) 105 if (pLogical == pMotherLogical) 110 { 106 { 111 G4Exception("G4PVReplica::G4PVReplica()", 107 G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002", 112 FatalException, "Cannot place 108 FatalException, "Cannot place a volume inside itself!"); 113 return; 109 return; 114 } 110 } 115 111 116 pMotherLogical->AddDaughter(this); 112 pMotherLogical->AddDaughter(this); 117 SetMotherLogical(pMotherLogical); 113 SetMotherLogical(pMotherLogical); 118 if (pMotherLogical->GetNoDaughters() != 1) 114 if (pMotherLogical->GetNoDaughters() != 1) 119 { 115 { 120 std::ostringstream message; 116 std::ostringstream message; 121 message << "Replica or parameterised volum 117 message << "Replica or parameterised volume must be the only daughter !" 122 << G4endl 118 << G4endl 123 << " Mother logical volume: " 119 << " Mother logical volume: " << pMotherLogical->GetName() 124 << G4endl 120 << G4endl 125 << " Replicated volume: " << p 121 << " Replicated volume: " << pName; 126 G4Exception("G4PVReplica::G4PVReplica()", 122 G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002", 127 FatalException, message); 123 FatalException, message); 128 return; 124 return; 129 } 125 } 130 CheckAndSetParameters (pAxis, nReplicas, wid 126 CheckAndSetParameters (pAxis, nReplicas, width, offset); 131 } 127 } 132 128 133 // ------------------------------------------- << 134 G4PVReplica::G4PVReplica( const G4String& pNam 129 G4PVReplica::G4PVReplica( const G4String& pName, 135 G4int nReplica 130 G4int nReplicas, 136 EAxis pAxis, 131 EAxis pAxis, 137 G4LogicalVolum 132 G4LogicalVolume* pLogical, 138 G4LogicalVolum << 133 G4LogicalVolume* pMotherLogical >> 134 ) 139 : G4VPhysicalVolume(nullptr, G4ThreeVector() 135 : G4VPhysicalVolume(nullptr, G4ThreeVector(), pName, pLogical, nullptr) 140 { 136 { 141 // Constructor for derived type(s) 137 // Constructor for derived type(s) 142 // Does not set mother volume or register th 138 // Does not set mother volume or register this one in mother volume 143 // ( To allow the correct type to be found 139 // ( To allow the correct type to be found in mother->AddDaughter ) 144 140 145 instanceID = subInstanceManager.CreateSubIns 141 instanceID = subInstanceManager.CreateSubInstance(); >> 142 G4MT_copyNo = -1; 146 143 147 if (pMotherLogical == nullptr) 144 if (pMotherLogical == nullptr) 148 { 145 { 149 std::ostringstream message; 146 std::ostringstream message; 150 message << "NULL pointer specified as moth 147 message << "NULL pointer specified as mother volume for " 151 << pName << "."; 148 << pName << "."; 152 G4Exception("G4PVReplica::G4PVReplica()", 149 G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002", 153 FatalException, message); 150 FatalException, message); 154 return; 151 return; 155 } 152 } 156 if (pLogical == pMotherLogical) 153 if (pLogical == pMotherLogical) 157 { 154 { 158 G4Exception("G4PVReplica::G4PVReplica()", 155 G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002", 159 FatalException, "Cannot place 156 FatalException, "Cannot place a volume inside itself!"); 160 return; 157 return; 161 } 158 } 162 CheckOnlyDaughter(pMotherLogical); 159 CheckOnlyDaughter(pMotherLogical); 163 /*** 160 /*** 164 if (pMotherLogical->GetNoDaughters() != 0) 161 if (pMotherLogical->GetNoDaughters() != 0) 165 { 162 { 166 std::ostringstream message; 163 std::ostringstream message; 167 message << "Replica or parameterised volum 164 message << "Replica or parameterised volume must be the only daughter !" 168 << G4endl 165 << G4endl 169 << " Mother logical volume: " 166 << " Mother logical volume: " << pMotherLogical->GetName() 170 << G4endl 167 << G4endl 171 << " Replicated volume: " << p 168 << " Replicated volume: " << pName; 172 G4Exception("G4PVReplica::G4PVReplica()", 169 G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002", 173 FatalException, message); 170 FatalException, message); 174 return; 171 return; 175 } 172 } 176 **/ 173 **/ 177 CheckAndSetParameters (pAxis, nReplicas, 0.0 174 CheckAndSetParameters (pAxis, nReplicas, 0.0, 0.0); 178 } 175 } 179 176 180 // ------------------------------------------- << 181 void G4PVReplica::CheckOnlyDaughter(G4LogicalV 177 void G4PVReplica::CheckOnlyDaughter(G4LogicalVolume* pMotherLogical) 182 { 178 { 183 if (pMotherLogical->GetNoDaughters() != 0) 179 if (pMotherLogical->GetNoDaughters() != 0) 184 { 180 { 185 std::ostringstream message; 181 std::ostringstream message; 186 message << "Replica or parameterised volum 182 message << "Replica or parameterised volume must be the only daughter !" 187 << G4endl 183 << G4endl 188 << " Mother logical volume: " 184 << " Mother logical volume: " << pMotherLogical->GetName() 189 << G4endl 185 << G4endl 190 << " Replicated volume: " << t 186 << " Replicated volume: " << this->GetName() << G4endl 191 << " Existing 'sister': " << p 187 << " Existing 'sister': " << pMotherLogical->GetDaughter(0) 192 188 ->GetName(); 193 G4Exception("G4PVReplica::G4PVReplica()", 189 G4Exception("G4PVReplica::G4PVReplica()", "GeomVol0002", 194 FatalException, message); 190 FatalException, message); 195 return; 191 return; 196 } 192 } 197 } 193 } 198 194 199 // ------------------------------------------- << 200 void G4PVReplica::CheckAndSetParameters( const 195 void G4PVReplica::CheckAndSetParameters( const EAxis pAxis, 201 const 196 const G4int nReplicas, 202 const 197 const G4double width, 203 const 198 const G4double offset) 204 { 199 { 205 if (nReplicas<1) 200 if (nReplicas<1) 206 { 201 { 207 G4Exception("G4PVReplica::CheckAndSetParam 202 G4Exception("G4PVReplica::CheckAndSetParameters()", "GeomVol0002", 208 FatalException, "Illegal numbe 203 FatalException, "Illegal number of replicas."); 209 } 204 } 210 fnReplicas=nReplicas; 205 fnReplicas=nReplicas; 211 if (width<0) 206 if (width<0) 212 { 207 { 213 G4Exception("G4PVReplica::CheckAndSetParam 208 G4Exception("G4PVReplica::CheckAndSetParameters()", "GeomVol0002", 214 FatalException, "Width must be 209 FatalException, "Width must be positive."); 215 } 210 } 216 fwidth = width; 211 fwidth = width; 217 foffset = offset; 212 foffset = offset; 218 faxis = pAxis; 213 faxis = pAxis; 219 214 220 // Create rotation matrix for phi axis case 215 // Create rotation matrix for phi axis case & check axis is valid 221 // 216 // 222 G4RotationMatrix* pRMat = nullptr; 217 G4RotationMatrix* pRMat = nullptr; 223 switch (faxis) 218 switch (faxis) 224 { 219 { 225 case kPhi: 220 case kPhi: 226 pRMat = new G4RotationMatrix(); 221 pRMat = new G4RotationMatrix(); 227 if (pRMat == nullptr) 222 if (pRMat == nullptr) 228 { 223 { 229 G4Exception("G4PVReplica::CheckAndSetP 224 G4Exception("G4PVReplica::CheckAndSetParameters()", "GeomVol0003", 230 FatalException, "Rotation 225 FatalException, "Rotation matrix allocation failed."); 231 } 226 } 232 SetRotation(pRMat); 227 SetRotation(pRMat); 233 break; 228 break; 234 case kRho: 229 case kRho: 235 case kXAxis: 230 case kXAxis: 236 case kYAxis: 231 case kYAxis: 237 case kZAxis: 232 case kZAxis: 238 case kUndefined: 233 case kUndefined: 239 break; 234 break; 240 default: 235 default: 241 G4Exception("G4PVReplica::CheckAndSetPar 236 G4Exception("G4PVReplica::CheckAndSetParameters()", "GeomVol0002", 242 FatalException, "Unknown axi 237 FatalException, "Unknown axis of replication."); 243 break; 238 break; 244 } 239 } 245 } 240 } 246 241 247 // ------------------------------------------- << 248 G4PVReplica::G4PVReplica( __void__& a ) 242 G4PVReplica::G4PVReplica( __void__& a ) 249 : G4VPhysicalVolume(a), faxis(kZAxis), fnRep 243 : G4VPhysicalVolume(a), faxis(kZAxis), fnReplicas(0), fwidth(0.), foffset(0.) 250 { 244 { 251 instanceID = subInstanceManager.CreateSubIns 245 instanceID = subInstanceManager.CreateSubInstance(); >> 246 G4MT_copyNo = -1; 252 } 247 } 253 248 254 // ------------------------------------------- << 249 G4PVReplica::~G4PVReplica() 255 G4PVReplica::~G4PVReplica() = default; << 250 { >> 251 if ( faxis==kPhi ) >> 252 { >> 253 delete GetRotation(); >> 254 } >> 255 } 256 256 257 // ------------------------------------------- << 258 G4bool G4PVReplica::IsMany() const 257 G4bool G4PVReplica::IsMany() const 259 { 258 { 260 return false; 259 return false; 261 } 260 } 262 261 263 // ------------------------------------------- << 264 G4int G4PVReplica::GetCopyNo() const 262 G4int G4PVReplica::GetCopyNo() const 265 { 263 { 266 return G4MT_copyNo; 264 return G4MT_copyNo; 267 } 265 } 268 266 269 // ------------------------------------------- << 270 void G4PVReplica::SetCopyNo(G4int newCopyNo) 267 void G4PVReplica::SetCopyNo(G4int newCopyNo) 271 { 268 { 272 G4MT_copyNo = newCopyNo; 269 G4MT_copyNo = newCopyNo; 273 } 270 } 274 271 275 // ------------------------------------------- << 276 G4bool G4PVReplica::IsReplicated() const 272 G4bool G4PVReplica::IsReplicated() const 277 { 273 { 278 return true; 274 return true; 279 } 275 } 280 276 281 // ------------------------------------------- << 282 G4bool G4PVReplica::IsParameterised() const 277 G4bool G4PVReplica::IsParameterised() const 283 { 278 { 284 return false; 279 return false; 285 } 280 } 286 281 287 // ------------------------------------------- << 288 G4VPVParameterisation* G4PVReplica::GetParamet 282 G4VPVParameterisation* G4PVReplica::GetParameterisation() const 289 { 283 { 290 return nullptr; 284 return nullptr; 291 } 285 } 292 286 293 // ------------------------------------------- << 294 G4int G4PVReplica::GetMultiplicity() const 287 G4int G4PVReplica::GetMultiplicity() const 295 { 288 { 296 return fnReplicas; 289 return fnReplicas; 297 } 290 } 298 291 299 // ------------------------------------------- << 300 EVolume G4PVReplica::VolumeType() const 292 EVolume G4PVReplica::VolumeType() const 301 { 293 { 302 return kReplica; 294 return kReplica; 303 } 295 } 304 296 305 // ------------------------------------------- << 306 void G4PVReplica::GetReplicationData( EAxis& a 297 void G4PVReplica::GetReplicationData( EAxis& axis, 307 G4int& n 298 G4int& nReplicas, 308 G4double 299 G4double& width, 309 G4double 300 G4double& offset, 310 G4bool& 301 G4bool& consuming ) const 311 { 302 { 312 axis = faxis; 303 axis = faxis; 313 nReplicas = fnReplicas; 304 nReplicas = fnReplicas; 314 width = fwidth; 305 width = fwidth; 315 offset = foffset; 306 offset = foffset; 316 consuming = true; 307 consuming = true; 317 } 308 } 318 309 319 // ------------------------------------------- << 320 G4bool G4PVReplica::IsRegularStructure() const 310 G4bool G4PVReplica::IsRegularStructure() const 321 { 311 { 322 return (fRegularVolsId != 0); 312 return (fRegularVolsId != 0); 323 } 313 } 324 314 325 // ------------------------------------------- << 326 G4int G4PVReplica::GetRegularStructureId() con 315 G4int G4PVReplica::GetRegularStructureId() const 327 { 316 { 328 return fRegularVolsId; 317 return fRegularVolsId; 329 } 318 } 330 319 331 // ------------------------------------------- << 332 void G4PVReplica::SetRegularStructureId( G4int 320 void G4PVReplica::SetRegularStructureId( G4int code ) 333 { 321 { 334 fRegularVolsId = code; 322 fRegularVolsId = code; 335 } 323 } 336 324 337 // ------------------------------------------- << 338 // Returns the private data instance manager. 325 // Returns the private data instance manager. 339 // 326 // 340 const G4PVRManager& G4PVReplica::GetSubInstanc 327 const G4PVRManager& G4PVReplica::GetSubInstanceManager() 341 { 328 { 342 return subInstanceManager; 329 return subInstanceManager; 343 } 330 } 344 331 345 // ------------------------------------------- << 346 // This method is similar to the constructor. 332 // This method is similar to the constructor. It is used by each worker 347 // thread to achieve the same effect as that o 333 // thread to achieve the same effect as that of the master thread exept 348 // to register the new created instance. This 334 // to register the new created instance. This method is invoked explicitly. 349 // It does not create a new G4PVReplica instan 335 // It does not create a new G4PVReplica instance. It only assigns the value 350 // for the fields encapsulated by the class G4 336 // for the fields encapsulated by the class G4ReplicaData. 351 // 337 // 352 void G4PVReplica::InitialiseWorker(G4PVReplica 338 void G4PVReplica::InitialiseWorker(G4PVReplica* pMasterObject) 353 { 339 { 354 340 355 G4VPhysicalVolume::InitialiseWorker( pMaster 341 G4VPhysicalVolume::InitialiseWorker( pMasterObject, nullptr, G4ThreeVector()); 356 subInstanceManager.SlaveCopySubInstanceArray 342 subInstanceManager.SlaveCopySubInstanceArray(); 357 G4MT_copyNo = -1; 343 G4MT_copyNo = -1; 358 344 359 // This call causes "self-assignment" of the << 345 // This call causes "self-assignment" of the input paramters 360 // Issue reported by DRD since TerminateWork << 346 // Issue reported by DRD since TerminateWorker below can be called 361 // at the same time by another thread. << 347 // at the same time by another thread 362 // What we need here is the split-class comp << 348 // What we need here is the splic-class component of this funciton 363 // funciton copied here. << 349 // that is copied here >> 350 // CheckAndSetParameters (faxis, fnReplicas, fwidth, foffset); 364 351 365 // Create rotation matrix for phi axis case 352 // Create rotation matrix for phi axis case & check axis is valid 366 // 353 // 367 G4RotationMatrix* pRMat = nullptr; 354 G4RotationMatrix* pRMat = nullptr; 368 switch (faxis) 355 switch (faxis) 369 { 356 { 370 case kPhi: 357 case kPhi: 371 pRMat = new G4RotationMatrix(); 358 pRMat = new G4RotationMatrix(); 372 if (pRMat == nullptr) 359 if (pRMat == nullptr) 373 { 360 { 374 G4Exception("G4PVReplica::InitialiseWo 361 G4Exception("G4PVReplica::InitialiseWorker(...)", "GeomVol0003", 375 FatalException, "Rotation 362 FatalException, "Rotation matrix allocation failed."); 376 } 363 } 377 SetRotation(pRMat); 364 SetRotation(pRMat); 378 break; 365 break; 379 case kRho: 366 case kRho: 380 case kXAxis: 367 case kXAxis: 381 case kYAxis: 368 case kYAxis: 382 case kZAxis: 369 case kZAxis: 383 case kUndefined: 370 case kUndefined: 384 break; 371 break; 385 default: 372 default: 386 G4Exception("G4PVReplica::InitialiseWork 373 G4Exception("G4PVReplica::InitialiseWorker(...)", "GeomVol0002", 387 FatalException, "Unknown axi 374 FatalException, "Unknown axis of replication."); 388 break; 375 break; 389 } 376 } 390 } 377 } 391 378 392 // ------------------------------------------- << 393 // This method is similar to the destructor. I 379 // This method is similar to the destructor. It is used by each worker 394 // thread to achieve the partial effect as tha 380 // thread to achieve the partial effect as that of the master thread. 395 // For G4PVReplica instances, it destroys the << 381 // For G4PVReplica instances, it destories the rotation matrix. 396 // 382 // 397 void G4PVReplica::TerminateWorker(G4PVReplica* 383 void G4PVReplica::TerminateWorker(G4PVReplica* /*pMasterObject*/) 398 { 384 { 399 if ( faxis==kPhi ) 385 if ( faxis==kPhi ) 400 { 386 { 401 delete GetRotation(); 387 delete GetRotation(); 402 } 388 } 403 } 389 } 404 390