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 // G4PVDivision Implementation file 27 // 28 // 26.05.03 - P.Arce, Initial version 29 // -------------------------------------------------------------------- 30 31 #include "G4PVDivision.hh" 32 #include "G4LogicalVolume.hh" 33 #include "G4VSolid.hh" 34 #include "G4ReflectedSolid.hh" 35 #include "G4ParameterisationBox.hh" 36 #include "G4ParameterisationTubs.hh" 37 #include "G4ParameterisationCons.hh" 38 #include "G4ParameterisationTrd.hh" 39 #include "G4ParameterisationPara.hh" 40 #include "G4ParameterisationPolycone.hh" 41 #include "G4ParameterisationPolyhedra.hh" 42 43 //-------------------------------------------------------------------------- 44 G4PVDivision::G4PVDivision(const G4String& pName, 45 G4LogicalVolume* pLogical, 46 G4LogicalVolume* pMotherLogical, 47 const EAxis pAxis, 48 const G4int nDivs, 49 const G4double width, 50 const G4double offset ) 51 : G4PVReplica(pName, nDivs, pAxis, pLogical, pMotherLogical) 52 { 53 if (pMotherLogical == nullptr) 54 { 55 std::ostringstream message; 56 message << "Invalid setup." << G4endl 57 << "NULL pointer specified as mother for volume: " << pName; 58 G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002", 59 FatalException, message); 60 return; 61 } 62 if (pLogical == pMotherLogical) 63 { 64 std::ostringstream message; 65 message << "Invalid setup." << G4endl 66 << "Cannot place a volume inside itself! Volume: " << pName; 67 G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002", 68 FatalException, message); 69 } 70 pMotherLogical->AddDaughter(this); 71 SetMotherLogical(pMotherLogical); 72 SetParameterisation(pMotherLogical, pAxis, nDivs, 73 width, offset, DivNDIVandWIDTH); 74 CheckAndSetParameters (pAxis, nDivs, width, offset, 75 DivNDIVandWIDTH, pMotherLogical); 76 } 77 78 //-------------------------------------------------------------------------- 79 G4PVDivision::G4PVDivision(const G4String& pName, 80 G4LogicalVolume* pLogical, 81 G4LogicalVolume* pMotherLogical, 82 const EAxis pAxis, 83 const G4int nDivs, 84 const G4double offset ) 85 : G4PVReplica(pName, nDivs, pAxis, pLogical, pMotherLogical) 86 { 87 if (pMotherLogical == nullptr) 88 { 89 std::ostringstream message; 90 message << "Invalid setup." << G4endl 91 << "NULL pointer specified as mother! Volume: " << pName; 92 G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002", 93 FatalException, message); 94 return; 95 } 96 if (pLogical == pMotherLogical) 97 { 98 std::ostringstream message; 99 message << "Invalid setup." << G4endl 100 << "Cannot place a volume inside itself! Volume: " << pName; 101 G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002", 102 FatalException, message); 103 } 104 pMotherLogical->AddDaughter(this); 105 SetMotherLogical(pMotherLogical); 106 SetParameterisation(pMotherLogical, pAxis, nDivs, 0., offset, DivNDIV); 107 CheckAndSetParameters (pAxis, nDivs, 0., offset, DivNDIV, pMotherLogical); 108 } 109 110 //-------------------------------------------------------------------------- 111 G4PVDivision::G4PVDivision(const G4String& pName, 112 G4LogicalVolume* pLogical, 113 G4LogicalVolume* pMotherLogical, 114 const EAxis pAxis, 115 const G4double width, 116 const G4double offset ) 117 : G4PVReplica(pName, 0, pAxis, pLogical, pMotherLogical) 118 { 119 if (pMotherLogical == nullptr) 120 { 121 std::ostringstream message; 122 message << "Invalid setup." << G4endl 123 << "NULL pointer specified as mother! Volume: " + pName; 124 G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002", 125 FatalException, message); 126 return; 127 } 128 if (pLogical == pMotherLogical) 129 { 130 std::ostringstream message; 131 message << "Invalid setup." << G4endl 132 << "Cannot place a volume inside itself! Volume: "+ pName; 133 G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002", 134 FatalException, message); 135 } 136 pMotherLogical->AddDaughter(this); 137 SetMotherLogical(pMotherLogical); 138 SetParameterisation(pMotherLogical, pAxis, 0, width, offset, DivWIDTH); 139 CheckAndSetParameters (pAxis, 0, width, offset, DivWIDTH, pMotherLogical); 140 } 141 142 //-------------------------------------------------------------------------- 143 G4PVDivision::G4PVDivision(const G4String& pName, 144 G4LogicalVolume* pLogical, 145 G4VPhysicalVolume* pMotherPhysical, 146 const EAxis pAxis, 147 const G4int nDivs, 148 const G4double width, 149 const G4double offset ) 150 : G4PVReplica(pName, nDivs, pAxis, pLogical, 151 pMotherPhysical != nullptr ? pMotherPhysical->GetLogicalVolume() : nullptr) 152 { 153 if (pMotherPhysical == nullptr) 154 { 155 std::ostringstream message; 156 message << "Invalid setup." << G4endl 157 << "NULL pointer specified as mother for volume: " << pName; 158 G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002", 159 FatalException, message); 160 return; 161 } 162 G4LogicalVolume* pMotherLogical = pMotherPhysical->GetLogicalVolume(); 163 if (pLogical == pMotherLogical) 164 { 165 std::ostringstream message; 166 message << "Invalid setup." << G4endl 167 << "Cannot place a volume inside itself! Volume: " << pName; 168 G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002", 169 FatalException, message); 170 } 171 pMotherLogical->AddDaughter(this); 172 SetMotherLogical(pMotherLogical); 173 SetParameterisation(pMotherLogical, pAxis, nDivs, 174 width, offset, DivNDIVandWIDTH); 175 CheckAndSetParameters (pAxis, nDivs, width, offset, 176 DivNDIVandWIDTH, pMotherLogical); 177 } 178 179 //-------------------------------------------------------------------------- 180 void 181 G4PVDivision::CheckAndSetParameters( const EAxis pAxis, 182 const G4int nDivs, 183 const G4double width, 184 const G4double offset, 185 DivisionType divType, 186 const G4LogicalVolume* pMotherLogical ) 187 { 188 if( divType == DivWIDTH ) 189 { 190 fnReplicas = fparam->GetNoDiv(); 191 } 192 else 193 { 194 fnReplicas = nDivs; 195 } 196 if (fnReplicas < 1 ) 197 { 198 G4Exception("G4PVDivision::CheckAndSetParameters()", "GeomDiv0002", 199 FatalException, "Illegal number of replicas!"); 200 } 201 202 if( divType != DivNDIV) 203 { 204 fwidth = fparam->GetWidth(); 205 } 206 else 207 { 208 fwidth = width; 209 } 210 if( fwidth < 0 ) 211 { 212 G4Exception("G4PVDivision::CheckAndSetParameters()", "GeomDiv0002", 213 FatalException, "Width must be positive!"); 214 } 215 216 foffset = offset; 217 fdivAxis = pAxis; 218 219 //!!!!! axis has to be x/y/z in G4VoxelLimits::GetMinExtent 220 // 221 if( pAxis == kRho || pAxis == kRadial3D || pAxis == kPhi ) 222 { 223 faxis = kZAxis; 224 } 225 else 226 { 227 faxis = pAxis; 228 } 229 230 // Create rotation matrix: for phi axis it will be changed 231 // in G4VPVParameterisation::ComputeTransformation, for others 232 // it will stay the unity 233 // 234 auto pRMat = new G4RotationMatrix(); 235 SetRotation(pRMat); 236 237 switch (faxis) 238 { 239 case kPhi: 240 break; 241 case kRho: 242 case kXAxis: 243 case kYAxis: 244 case kZAxis: 245 break; 246 default: 247 G4Exception("G4PVDivision::CheckAndSetParameters()", "GeomDiv0002", 248 FatalException, "Unknown axis of replication."); 249 break; 250 } 251 252 253 //----- Check that mother solid is of the same type than 254 // daughter solid (otherwise, the corresponding 255 // Parameterisation::ComputeDimension() will not be called) 256 // 257 G4String msolType = pMotherLogical->GetSolid()->GetEntityType(); 258 G4String dsolType = GetLogicalVolume()->GetSolid()->GetEntityType(); 259 if( msolType != dsolType && ( msolType != "G4Trd" || dsolType != "G4Trap" ) ) 260 { 261 std::ostringstream message; 262 message << "Incorrect solid type for division of volume " 263 << GetName() << "." << G4endl 264 << "It is: " << msolType 265 << ", while it should be: " << dsolType << "!"; 266 G4Exception("G4PVDivision::CheckAndSetParameters()", 267 "GeomDiv0002", FatalException, message ); 268 } 269 } 270 271 //-------------------------------------------------------------------------- 272 G4PVDivision::~G4PVDivision() = default; 273 274 //-------------------------------------------------------------------------- 275 EAxis G4PVDivision::GetDivisionAxis() const 276 { 277 return fdivAxis; 278 } 279 280 //-------------------------------------------------------------------------- 281 G4bool G4PVDivision::IsParameterised() const 282 { 283 return true; 284 } 285 286 //-------------------------------------------------------------------------- 287 G4bool G4PVDivision::IsMany() const 288 { 289 return false; 290 } 291 292 //-------------------------------------------------------------------------- 293 G4bool G4PVDivision::IsReplicated() const 294 { 295 return true; 296 } 297 298 //-------------------------------------------------------------------------- 299 G4int G4PVDivision::GetMultiplicity() const 300 { 301 return fnReplicas; 302 } 303 304 //-------------------------------------------------------------------------- 305 G4VPVParameterisation* G4PVDivision::GetParameterisation() const 306 { 307 return fparam; 308 } 309 310 //-------------------------------------------------------------------------- 311 void G4PVDivision::GetReplicationData(EAxis& axis, 312 G4int& nDivs, 313 G4double& width, 314 G4double& offset, 315 G4bool& consuming ) const 316 { 317 axis = faxis; 318 nDivs = fnReplicas; 319 width = fwidth; 320 offset = foffset; 321 consuming = false; 322 } 323 324 //-------------------------------------------------------------------------- 325 EVolume G4PVDivision::VolumeType() const 326 { 327 return kParameterised; 328 } 329 330 //-------------------------------------------------------------------------- 331 // TODO: this method should check that the child lv is of the correct type, 332 // else the ComputeDimensions will never be called 333 // 334 void G4PVDivision::SetParameterisation( G4LogicalVolume* motherLogical, 335 const EAxis axis, 336 const G4int nDivs, 337 const G4double width, 338 const G4double offset, 339 DivisionType divType ) 340 { 341 // Check that solid is compatible with mother solid and axis of division 342 // CheckSolid( solid, motherSolid ); 343 // G4cout << " Axis " << axis << G4endl; 344 345 G4VSolid* mSolid = motherLogical->GetSolid(); 346 G4String mSolidType = mSolid->GetEntityType(); 347 348 // If the solid is a reflected one, update type to its 349 // real constituent solid. 350 // 351 if (mSolidType == "G4ReflectedSolid") 352 { 353 mSolidType = ((G4ReflectedSolid*)mSolid)->GetConstituentMovedSolid() 354 ->GetEntityType(); 355 } 356 357 // Parameterisation type depend of mother solid type and axis of division 358 // 359 if( mSolidType == "G4Box" ) 360 { 361 switch( axis ) 362 { 363 case kXAxis: 364 fparam = new G4ParameterisationBoxX( axis, nDivs, width, 365 offset, mSolid, divType ); 366 break; 367 case kYAxis: 368 fparam = new G4ParameterisationBoxY( axis, nDivs, width, 369 offset, mSolid, divType ); 370 break; 371 case kZAxis: 372 fparam = new G4ParameterisationBoxZ( axis, nDivs, width, 373 offset, mSolid, divType ); 374 break; 375 default: 376 ErrorInAxis( axis, mSolid ); 377 break; 378 } 379 } 380 else if( mSolidType == "G4Tubs" ) 381 { 382 switch( axis ) 383 { 384 case kRho: 385 fparam = new G4ParameterisationTubsRho( axis, nDivs, width, 386 offset, mSolid, divType ); 387 break; 388 case kPhi: 389 fparam = new G4ParameterisationTubsPhi( axis, nDivs, width, 390 offset, mSolid, divType ); 391 break; 392 case kZAxis: 393 fparam = new G4ParameterisationTubsZ( axis, nDivs, width, 394 offset, mSolid, divType ); 395 break; 396 default: 397 ErrorInAxis( axis, mSolid ); 398 break; 399 } 400 } 401 else if( mSolidType == "G4Cons" ) 402 { 403 switch( axis ) 404 { 405 case kRho: 406 fparam = new G4ParameterisationConsRho( axis, nDivs, width, 407 offset, mSolid, divType ); 408 break; 409 case kPhi: 410 fparam = new G4ParameterisationConsPhi( axis, nDivs, width, 411 offset, mSolid, divType ); 412 break; 413 case kZAxis: 414 fparam = new G4ParameterisationConsZ( axis, nDivs, width, 415 offset, mSolid, divType ); 416 break; 417 default: 418 ErrorInAxis( axis, mSolid ); 419 break; 420 } 421 } 422 else if( mSolidType == "G4Trd" ) 423 { 424 switch( axis ) 425 { 426 case kXAxis: 427 fparam = new G4ParameterisationTrdX( axis, nDivs, width, 428 offset, mSolid, divType ); 429 break; 430 case kYAxis: 431 fparam = new G4ParameterisationTrdY( axis, nDivs, width, 432 offset, mSolid, divType ); 433 break; 434 case kZAxis: 435 fparam = new G4ParameterisationTrdZ( axis, nDivs, width, 436 offset, mSolid, divType ); 437 break; 438 default: 439 ErrorInAxis( axis, mSolid ); 440 break; 441 } 442 } 443 else if( mSolidType == "G4Para" ) 444 { 445 switch( axis ) 446 { 447 case kXAxis: 448 fparam = new G4ParameterisationParaX( axis, nDivs, width, 449 offset, mSolid, divType ); 450 break; 451 case kYAxis: 452 fparam = new G4ParameterisationParaY( axis, nDivs, width, 453 offset, mSolid, divType ); 454 break; 455 case kZAxis: 456 fparam = new G4ParameterisationParaZ( axis, nDivs, width, 457 offset, mSolid, divType ); 458 break; 459 default: 460 ErrorInAxis( axis, mSolid ); 461 break; 462 } 463 } 464 // else if( mSolidType == "G4Trap" ) 465 // { 466 // } 467 else if( mSolidType == "G4Polycone" ) 468 { 469 switch( axis ) 470 { 471 case kRho: 472 fparam = new G4ParameterisationPolyconeRho( axis, nDivs, width, 473 offset, mSolid, divType ); 474 break; 475 case kPhi: 476 fparam = new G4ParameterisationPolyconePhi( axis, nDivs, width, 477 offset, mSolid, divType ); 478 break; 479 case kZAxis: 480 fparam = new G4ParameterisationPolyconeZ( axis, nDivs, width, 481 offset, mSolid, divType ); 482 break; 483 default: 484 ErrorInAxis( axis, mSolid ); 485 break; 486 } 487 } 488 else if( mSolidType == "G4Polyhedra" ) 489 { 490 switch( axis ) 491 { 492 case kRho: 493 fparam = new G4ParameterisationPolyhedraRho( axis, nDivs, width, 494 offset, mSolid, divType ); 495 break; 496 case kPhi: 497 fparam = new G4ParameterisationPolyhedraPhi( axis, nDivs, width, 498 offset, mSolid, divType ); 499 break; 500 case kZAxis: 501 fparam = new G4ParameterisationPolyhedraZ( axis, nDivs, width, 502 offset, mSolid, divType ); 503 break; 504 default: 505 ErrorInAxis( axis, mSolid ); 506 break; 507 } 508 } 509 else 510 { 511 std::ostringstream message; 512 message << "Solid type " << mSolidType << " not supported!" << G4endl 513 << "Divisions for " << mSolidType << " are not implemented."; 514 G4Exception("G4PVDivision::SetParameterisation()", "GeomDiv0001", 515 FatalException, message); 516 } 517 } 518 519 //-------------------------------------------------------------------------- 520 void G4PVDivision::ErrorInAxis( EAxis axis, G4VSolid* solid ) 521 { 522 G4String error = "Trying to divide solid " + solid->GetName() 523 + " of type " + solid->GetEntityType() + " along axis "; 524 switch( axis ) 525 { 526 case kXAxis: 527 error += "X."; 528 break; 529 case kYAxis: 530 error += "Y."; 531 break; 532 case kZAxis: 533 error += "Z."; 534 break; 535 case kRho: 536 error += "Rho."; 537 break; 538 case kRadial3D: 539 error += "Radial3D."; 540 break; 541 case kPhi: 542 error += "Phi."; 543 break; 544 default: 545 break; 546 } 547 G4Exception("G4PVDivision::ErrorInAxis()", "GeomDiv0002", 548 FatalException, error); 549 } 550 551 // The next methods are for specialised repeated volumes (replicas, 552 // parameterised vol.) which are completely regular. 553 // Currently this is not applicable to divisions ( J.A. Nov 2005 ) 554 555 // ---------------------------------------------------------------------- 556 // IsRegularStructure() 557 // 558 G4bool G4PVDivision::IsRegularStructure() const 559 { 560 return false; 561 } 562 563 // ---------------------------------------------------------------------- 564 // GetRegularStructureId() 565 // 566 G4int G4PVDivision::GetRegularStructureId() const 567 { 568 return 0; 569 } 570