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 // Class G4ReflectionFactory Implementation 27 // 28 // Decomposition of a general transformation 29 // that can include reflection in a "reflection-free" transformation: 30 // 31 // x(inM') = TG*x(inM) TG - general transformation 32 // = T*(R*x(inM)) T - "reflection-free" transformation 33 // = T* x(inReflM) 34 // 35 // Daughters transformation: 36 // When a volume V containing daughter D with transformation TD 37 // is placed in mother M with a general tranformation TGV, 38 // the TGV is decomposed, 39 // new reflected volume ReflV containing a new daughter ReflD 40 // with reflected transformation ReflTD is created: 41 // 42 // x(inV) = TD * x(inD); 43 // x(inM) = TGV * x(inV) 44 // = TV * R * x(inV) 45 // = TV * R * TD * x(inD) 46 // = TV * R*TD*R-1 * R*x(inD) 47 // = TV * ReflTD * x(inReflD) 48 // 49 // Author: Ivana Hrivnacova (Ivana.Hrivnacova@cern.ch), 16.10.2001 50 // -------------------------------------------------------------------- 51 52 #include "G4ReflectionFactory.hh" 53 #include "G4ReflectedSolid.hh" 54 #include "G4Region.hh" 55 #include "G4LogicalVolume.hh" 56 #include "G4PVPlacement.hh" 57 #include "G4PVReplica.hh" 58 #include "G4VPVDivisionFactory.hh" 59 #include "G4GeometryTolerance.hh" 60 61 G4ThreadLocal G4ReflectionFactory* G4ReflectionFactory::fInstance = nullptr; 62 const G4String G4ReflectionFactory::fDefaultNameExtension = "_refl"; 63 const G4Scale3D G4ReflectionFactory::fScale = G4ScaleZ3D(-1.0); 64 65 //_____________________________________________________________________________ 66 67 G4ReflectionFactory* G4ReflectionFactory::Instance() 68 { 69 // Static singleton access method. 70 // --- 71 72 if (fInstance == nullptr) { fInstance = new G4ReflectionFactory(); } 73 74 return fInstance; 75 } 76 77 //_____________________________________________________________________________ 78 79 G4ReflectionFactory::G4ReflectionFactory() 80 : fNameExtension(fDefaultNameExtension) 81 { 82 // Protected singleton constructor. 83 // --- 84 85 fScalePrecision = 10. 86 * G4GeometryTolerance::GetInstance()->GetSurfaceTolerance(); 87 fInstance = this; 88 } 89 90 //_____________________________________________________________________________ 91 92 G4ReflectionFactory::~G4ReflectionFactory() 93 { 94 delete fInstance; 95 } 96 97 // 98 // public methods 99 // 100 101 //_____________________________________________________________________________ 102 103 G4PhysicalVolumesPair 104 G4ReflectionFactory::Place( const G4Transform3D& transform3D, 105 const G4String& name, 106 G4LogicalVolume* LV, 107 G4LogicalVolume* motherLV, 108 G4bool isMany, 109 G4int copyNo, 110 G4bool surfCheck) 111 { 112 // Evaluates the passed transformation; if it contains reflection 113 // it performs its decomposition, creates new reflected solid and 114 // logical volume (or retrieves them from a map if the reflected 115 // objects were already created), transforms the daughters (if present) 116 // and place it in the given mother. 117 // The result is a pair of physical volumes; 118 // the second physical volume is a placement in a reflected mother 119 // - or nullptr if mother LV was not reflected. 120 // --- 121 122 if (fVerboseLevel>0) 123 { 124 G4cout << "Place " << name << " lv " << LV << " " 125 << LV->GetName() << G4endl; 126 } 127 128 // decompose transformation 129 G4Scale3D scale; 130 G4Rotate3D rotation; 131 G4Translate3D translation; 132 133 transform3D.getDecomposition(scale, rotation, translation); 134 G4Transform3D pureTransform3D = translation * rotation; 135 136 //PrintTransform(transform3D); 137 //PrintTransform(pureTransform3D); 138 139 // check that scale correspond to fScale 140 // 141 CheckScale(scale); 142 143 // 144 // reflection IS NOT present in transform3D 145 // 146 147 if (!IsReflection(scale)) 148 { 149 if (fVerboseLevel>0) 150 G4cout << "Scale positive" << G4endl; 151 152 G4VPhysicalVolume* pv1 153 = new G4PVPlacement(pureTransform3D, LV, name, 154 motherLV, isMany, copyNo, surfCheck); 155 156 G4VPhysicalVolume* pv2 = nullptr; 157 if (G4LogicalVolume* reflMotherLV = GetReflectedLV(motherLV)) 158 { 159 // if mother was reflected 160 // reflect this LV and place it in reflected mother 161 162 pv2 = new G4PVPlacement(fScale * (pureTransform3D * fScale.inverse()), 163 ReflectLV(LV, surfCheck), name, reflMotherLV, 164 isMany, copyNo, surfCheck); 165 } 166 167 return {pv1, pv2}; 168 } 169 170 // 171 // reflection IS present in transform3D 172 // 173 174 if (fVerboseLevel>0) 175 G4cout << "scale negative" << G4endl; 176 177 G4VPhysicalVolume* pv1 178 = new G4PVPlacement(pureTransform3D, ReflectLV(LV, surfCheck), name, 179 motherLV, isMany, copyNo, surfCheck); 180 181 G4VPhysicalVolume* pv2 = nullptr; 182 if (G4LogicalVolume* reflMotherLV = GetReflectedLV(motherLV)) 183 { 184 185 // if mother was reflected 186 // place the refLV consituent in reflected mother 187 188 pv2 = new G4PVPlacement(fScale * (pureTransform3D * fScale.inverse()), 189 LV, name, reflMotherLV, isMany, copyNo, surfCheck); 190 } 191 192 return {pv1, pv2}; 193 } 194 195 196 //_____________________________________________________________________________ 197 198 G4PhysicalVolumesPair 199 G4ReflectionFactory::Replicate(const G4String& name, 200 G4LogicalVolume* LV, 201 G4LogicalVolume* motherLV, 202 EAxis axis, 203 G4int nofReplicas, 204 G4double width, 205 G4double offset) 206 { 207 // Creates replica in given mother. 208 // The result is a pair of physical volumes; 209 // the second physical volume is a replica in a reflected mother 210 // - or nullptr if mother LV was not reflected. 211 // --- 212 213 if (fVerboseLevel>0) 214 { 215 G4cout << "Replicate " << name << " lv " << LV << " " 216 << LV->GetName() << G4endl; 217 } 218 219 G4VPhysicalVolume* pv1 220 = new G4PVReplica(name, LV, motherLV, axis, nofReplicas, width, offset); 221 222 G4VPhysicalVolume* pv2 = nullptr; 223 if (G4LogicalVolume* reflMotherLV = GetReflectedLV(motherLV)) 224 { 225 // if mother was reflected 226 // reflect the LV and replicate it in reflected mother 227 228 pv2 = new G4PVReplica(name, ReflectLV(LV), reflMotherLV, 229 axis, nofReplicas, width, offset); 230 } 231 232 return {pv1, pv2}; 233 } 234 235 //_____________________________________________________________________________ 236 237 G4PhysicalVolumesPair 238 G4ReflectionFactory::Divide(const G4String& name, 239 G4LogicalVolume* LV, 240 G4LogicalVolume* motherLV, 241 EAxis axis, 242 G4int nofDivisions, 243 G4double width, 244 G4double offset) 245 { 246 // Creates division in the given mother. 247 // The result is a pair of physical volumes; 248 // the second physical volume is a division in a reflected mother 249 // or nullptr if mother LV was not reflected. 250 // --- 251 252 if (fVerboseLevel>0) 253 { 254 G4cout << "Divide " << name << " lv " << LV << " " 255 << LV->GetName() << G4endl; 256 } 257 258 G4VPVDivisionFactory* divisionFactory = GetPVDivisionFactory(); 259 260 G4VPhysicalVolume* pv1 = divisionFactory 261 ->CreatePVDivision(name, LV, motherLV, axis, nofDivisions, width, offset); 262 263 G4VPhysicalVolume* pv2 = nullptr; 264 if (G4LogicalVolume* reflMotherLV = GetReflectedLV(motherLV)) 265 { 266 // if mother was reflected 267 // reflect the LV and replicate it in reflected mother 268 269 pv2 = divisionFactory->CreatePVDivision(name, ReflectLV(LV), reflMotherLV, 270 axis, nofDivisions, width, offset); 271 } 272 273 return {pv1, pv2}; 274 } 275 276 277 //_____________________________________________________________________________ 278 279 G4PhysicalVolumesPair 280 G4ReflectionFactory::Divide(const G4String& name, 281 G4LogicalVolume* LV, 282 G4LogicalVolume* motherLV, 283 EAxis axis, 284 G4int nofDivisions, 285 G4double offset) 286 { 287 // Creates division in the given mother. 288 // The result is a pair of physical volumes; 289 // the second physical volume is a division in a reflected mother 290 // or nullptr if mother LV was not reflected. 291 // --- 292 293 if (fVerboseLevel>0) 294 { 295 G4cout << "Divide " << name << " lv " << LV << " " 296 << LV->GetName() << G4endl; 297 } 298 299 G4VPVDivisionFactory* divisionFactory = GetPVDivisionFactory(); 300 301 G4VPhysicalVolume* pv1 = divisionFactory 302 ->CreatePVDivision(name, LV, motherLV, axis, nofDivisions, offset); 303 304 G4VPhysicalVolume* pv2 = nullptr; 305 if (G4LogicalVolume* reflMotherLV = GetReflectedLV(motherLV)) 306 { 307 // if mother was reflected 308 // reflect the LV and replicate it in reflected mother 309 310 pv2 = divisionFactory->CreatePVDivision(name, ReflectLV(LV), reflMotherLV, 311 axis, nofDivisions, offset); 312 } 313 314 return {pv1, pv2}; 315 } 316 317 318 //_____________________________________________________________________________ 319 320 G4PhysicalVolumesPair 321 G4ReflectionFactory::Divide(const G4String& name, 322 G4LogicalVolume* LV, 323 G4LogicalVolume* motherLV, 324 EAxis axis, 325 G4double width, 326 G4double offset) 327 { 328 // Creates division in the given mother. 329 // The result is a pair of physical volumes; 330 // the second physical volume is a division in a reflected mother 331 // or nullptr if mother LV was not reflected. 332 // --- 333 334 if (fVerboseLevel>0) 335 { 336 G4cout << "Divide " << name << " lv " << LV << " " 337 << LV->GetName() << G4endl; 338 } 339 340 G4VPVDivisionFactory* divisionFactory = GetPVDivisionFactory(); 341 342 G4VPhysicalVolume* pv1 = divisionFactory 343 -> CreatePVDivision(name, LV, motherLV, axis, width, offset); 344 345 G4VPhysicalVolume* pv2 = nullptr; 346 if (G4LogicalVolume* reflMotherLV = GetReflectedLV(motherLV)) 347 { 348 // if mother was reflected 349 // reflect the LV and replicate it in reflected mother 350 351 pv2 = divisionFactory->CreatePVDivision(name, ReflectLV(LV), reflMotherLV, 352 axis, width, offset); 353 } 354 355 return {pv1, pv2}; 356 } 357 358 359 // 360 // private methods 361 // 362 363 //_____________________________________________________________________________ 364 365 G4LogicalVolume* G4ReflectionFactory::ReflectLV(G4LogicalVolume* LV, 366 G4bool surfCheck) 367 { 368 // Gets/creates the reflected solid and logical volume 369 // and copies + transforms LV daughters. 370 // --- 371 372 G4LogicalVolume* refLV = GetReflectedLV(LV); 373 374 if (refLV == nullptr) 375 { 376 377 // create new (reflected) objects 378 // 379 refLV = CreateReflectedLV(LV); 380 381 // process daughters 382 // 383 ReflectDaughters(LV, refLV, surfCheck); 384 385 // check if to be set as root region 386 // 387 if (LV->IsRootRegion()) 388 { 389 LV->GetRegion()->AddRootLogicalVolume(refLV); 390 } 391 } 392 393 return refLV; 394 } 395 396 //_____________________________________________________________________________ 397 398 G4LogicalVolume* G4ReflectionFactory::CreateReflectedLV(G4LogicalVolume* LV) 399 { 400 // Creates the reflected solid and logical volume 401 // and add the logical volumes pair in the maps. 402 // --- 403 404 // consistency check 405 // 406 if (fReflectedLVMap.find(LV) != fReflectedLVMap.end()) 407 { 408 std::ostringstream message; 409 message << "Invalid reflection for volume: " 410 << LV->GetName() << G4endl 411 << "Cannot be applied to a volume already reflected !"; 412 G4Exception("G4ReflectionFactory::CreateReflectedLV()", 413 "GeomVol0002", FatalException, message); 414 } 415 416 G4VSolid* refSolid 417 = new G4ReflectedSolid(LV->GetSolid()->GetName() + fNameExtension, 418 LV->GetSolid(), fScale); 419 420 auto refLV 421 = new G4LogicalVolume(refSolid, 422 LV->GetMaterial(), 423 LV->GetName() + fNameExtension, 424 LV->GetFieldManager(), 425 LV->GetSensitiveDetector(), 426 LV->GetUserLimits()); 427 428 if (LV->GetVisAttributes() != nullptr) { 429 refLV->SetVisAttributes(*LV->GetVisAttributes()); // vis-attributes 430 } 431 refLV->SetBiasWeight(LV->GetBiasWeight()); // biasing weight 432 if (LV->IsRegion()) 433 { 434 refLV->SetRegion(LV->GetRegion()); // set a region in case 435 } 436 437 fConstituentLVMap[LV] = refLV; 438 fReflectedLVMap[refLV] = LV; 439 440 return refLV; 441 } 442 443 //_____________________________________________________________________________ 444 445 void G4ReflectionFactory::ReflectDaughters(G4LogicalVolume* LV, 446 G4LogicalVolume* refLV, 447 G4bool surfCheck) 448 { 449 // Reflects daughters recursively. 450 // --- 451 452 if (fVerboseLevel>0) 453 { 454 G4cout << "G4ReflectionFactory::ReflectDaughters(): " 455 << LV->GetNoDaughters() << " of " << LV->GetName() << G4endl; 456 } 457 458 for (std::size_t i=0; i<LV->GetNoDaughters(); ++i) 459 { 460 G4VPhysicalVolume* dPV = LV->GetDaughter((G4int)i); 461 462 if (!dPV->IsReplicated()) 463 { 464 ReflectPVPlacement(dPV, refLV, surfCheck); 465 } 466 else if (dPV->GetParameterisation() == nullptr) 467 { 468 ReflectPVReplica(dPV, refLV); 469 } 470 else if ((G4VPVDivisionFactory::Instance() != nullptr) && 471 G4VPVDivisionFactory::Instance()->IsPVDivision(dPV)) 472 { 473 ReflectPVDivision(dPV, refLV); 474 } 475 else 476 { 477 ReflectPVParameterised(dPV, refLV, surfCheck); 478 } 479 } 480 } 481 482 //_____________________________________________________________________________ 483 484 void G4ReflectionFactory::ReflectPVPlacement(G4VPhysicalVolume* dPV, 485 G4LogicalVolume* refLV, 486 G4bool surfCheck) 487 { 488 // Copies and transforms daughter of PVPlacement type of 489 // a constituent volume into a reflected volume. 490 // --- 491 492 G4LogicalVolume* dLV = dPV->GetLogicalVolume(); 493 494 // update daughter transformation 495 // 496 G4Transform3D dt(dPV->GetObjectRotationValue(), dPV->GetObjectTranslation()); 497 dt = fScale * (dt * fScale.inverse()); 498 499 G4LogicalVolume* refDLV; 500 501 if (fVerboseLevel>0) 502 G4cout << "Daughter: " << dPV << " " << dLV->GetName(); 503 504 if (!IsReflected(dLV)) 505 { 506 507 if (fVerboseLevel>0) 508 G4cout << " will be reflected." << G4endl; 509 510 // get reflected volume if already created 511 refDLV = GetReflectedLV(dLV); 512 513 if (refDLV == nullptr) 514 { 515 // create new daughter solid and logical volume 516 // 517 refDLV = CreateReflectedLV(dLV); 518 519 // recursive call 520 // 521 ReflectDaughters(dLV, refDLV, surfCheck); 522 } 523 524 // create new daughter physical volume 525 // with updated transformation 526 527 new G4PVPlacement(dt, refDLV, dPV->GetName(), refLV, 528 dPV->IsMany(), dPV->GetCopyNo(), surfCheck); 529 530 } 531 else 532 { 533 if (fVerboseLevel>0) 534 G4cout << " will be reconstitued." << G4endl; 535 536 refDLV = GetConstituentLV(dLV); 537 538 new G4PVPlacement(dt, refDLV, dPV->GetName(), refLV, 539 dPV->IsMany(), dPV->GetCopyNo(), surfCheck); 540 } 541 } 542 543 //_____________________________________________________________________________ 544 545 void G4ReflectionFactory::ReflectPVReplica(G4VPhysicalVolume* dPV, 546 G4LogicalVolume* refLV) 547 { 548 // Copies and transforms daughter of PVReplica type of 549 // a constituent volume into a reflected volume. 550 // --- 551 552 G4LogicalVolume* dLV = dPV->GetLogicalVolume(); 553 554 // get replication data 555 // 556 EAxis axis; 557 G4int nofReplicas; 558 G4double width; 559 G4double offset; 560 G4bool consuming; 561 562 dPV->GetReplicationData(axis, nofReplicas, width, offset, consuming); 563 564 G4LogicalVolume* refDLV; 565 566 if (fVerboseLevel>0) 567 G4cout << "Daughter: " << dPV << " " << dLV->GetName(); 568 569 if (!IsReflected(dLV)) 570 { 571 if (fVerboseLevel>0) 572 G4cout << " will be reflected." << G4endl; 573 574 // get reflected volume if already created 575 // 576 refDLV = GetReflectedLV(dLV); 577 578 if (refDLV == nullptr) 579 { 580 // create new daughter solid and logical volume 581 // 582 refDLV = CreateReflectedLV(dLV); 583 584 // recursive call 585 // 586 ReflectDaughters(dLV, refDLV); 587 } 588 589 // create new daughter replica 590 // 591 new G4PVReplica(dPV->GetName(), refDLV, refLV, 592 axis, nofReplicas, width, offset); 593 } 594 else 595 { 596 if (fVerboseLevel>0) 597 G4cout << " will be reconstitued." << G4endl; 598 599 refDLV = GetConstituentLV(dLV); 600 601 new G4PVReplica(dPV->GetName(), refDLV, refLV, 602 axis, nofReplicas, width, offset); 603 } 604 } 605 606 //_____________________________________________________________________________ 607 608 void G4ReflectionFactory::ReflectPVDivision(G4VPhysicalVolume* dPV, 609 G4LogicalVolume* refLV) 610 { 611 // Copies and transforms daughter of PVDivision type of 612 // a constituent volume into a reflected volume. 613 // --- 614 615 G4VPVDivisionFactory* divisionFactory = GetPVDivisionFactory(); 616 617 G4LogicalVolume* dLV = dPV->GetLogicalVolume(); 618 619 // get parameterisation data 620 // 621 G4VPVParameterisation* param = dPV->GetParameterisation(); 622 623 G4LogicalVolume* refDLV; 624 625 if (fVerboseLevel>0) 626 G4cout << "Daughter: " << dPV << " " << dLV->GetName(); 627 628 if (!IsReflected(dLV)) 629 { 630 if (fVerboseLevel>0) 631 G4cout << " will be reflected." << G4endl; 632 633 // get reflected volume if already created 634 // 635 refDLV = GetReflectedLV(dLV); 636 637 if (refDLV == nullptr) 638 { 639 // create new daughter solid and logical volume 640 // 641 refDLV = CreateReflectedLV(dLV); 642 643 // recursive call 644 // 645 ReflectDaughters(dLV, refDLV); 646 } 647 648 // create new daughter replica 649 // 650 divisionFactory->CreatePVDivision(dPV->GetName(), refDLV, refLV, param); 651 } 652 else 653 { 654 if (fVerboseLevel>0) 655 G4cout << " will be reconstitued." << G4endl; 656 657 refDLV = GetConstituentLV(dLV); 658 659 divisionFactory->CreatePVDivision(dPV->GetName(), refDLV, refLV, param); 660 } 661 } 662 663 //_____________________________________________________________________________ 664 665 void G4ReflectionFactory::ReflectPVParameterised(G4VPhysicalVolume* dPV, 666 G4LogicalVolume*, G4bool) 667 { 668 // Not implemented. 669 // Should copy and transform daughter of PVReplica type of 670 // a constituent volume into a reflected volume. 671 // --- 672 673 std::ostringstream message; 674 message << "Not yet implemented. Volume: " << dPV->GetName() << G4endl 675 << "Reflection of parameterised volumes is not yet implemented."; 676 G4Exception("G4ReflectionFactory::ReflectPVParameterised()", 677 "GeomVol0001", FatalException, message); 678 } 679 680 //_____________________________________________________________________________ 681 682 G4LogicalVolume* 683 G4ReflectionFactory::GetConstituentLV(G4LogicalVolume* reflLV) const 684 { 685 // Returns the consituent volume of the given reflected volume, 686 // nullptr if the given reflected volume was not found. 687 // --- 688 689 auto it = fReflectedLVMap.find(reflLV); 690 691 if (it == fReflectedLVMap.end()) return nullptr; 692 693 return (*it).second; 694 } 695 696 //_____________________________________________________________________________ 697 698 G4LogicalVolume* 699 G4ReflectionFactory::GetReflectedLV(G4LogicalVolume* lv) const 700 { 701 // Returns the reflected volume of the given consituent volume, 702 // nullptr if the given volume was not reflected. 703 // --- 704 705 auto it = fConstituentLVMap.find(lv); 706 707 if (it == fConstituentLVMap.end()) return nullptr; 708 709 return (*it).second; 710 } 711 712 //_____________________________________________________________________________ 713 714 G4bool G4ReflectionFactory::IsConstituent(G4LogicalVolume* lv) const 715 { 716 // Returns true if the given volume has been already reflected 717 // (is in the map of constituent volumes). 718 // --- 719 720 return (fConstituentLVMap.find(lv) != fConstituentLVMap.end()); 721 } 722 723 //_____________________________________________________________________________ 724 725 G4bool G4ReflectionFactory::IsReflected(G4LogicalVolume* lv) const 726 { 727 // Returns true if the given volume is a reflected volume 728 // (is in the map reflected volumes). 729 // --- 730 731 return (fReflectedLVMap.find(lv) != fReflectedLVMap.end()); 732 } 733 734 //_____________________________________________________________________________ 735 736 G4bool G4ReflectionFactory::IsReflection(const G4Scale3D& scale) const 737 { 738 // Returns true if the scale is negative, false otherwise. 739 // --- 740 741 return scale(0,0)*scale(1,1)*scale(2,2) < 0.; 742 } 743 744 //_____________________________________________________________________________ 745 746 const G4ReflectedVolumesMap& 747 G4ReflectionFactory::GetReflectedVolumesMap() const 748 { 749 return fReflectedLVMap; 750 } 751 752 //_____________________________________________________________________________ 753 754 void G4ReflectionFactory::Clean() 755 { 756 fConstituentLVMap.clear(); 757 fReflectedLVMap.clear(); 758 } 759 760 //_____________________________________________________________________________ 761 762 void G4ReflectionFactory::PrintConstituentLVMap() 763 { 764 // temporary - for debugging purpose 765 // --- 766 767 LogicalVolumesMapIterator it; 768 for (it = fConstituentLVMap.begin(); it != fConstituentLVMap.end(); ++it) 769 { 770 G4cout << "lv: " << (*it).first << " lv_refl: " << (*it).second << G4endl; 771 } 772 G4cout << G4endl; 773 } 774 775 //_____________________________________________________________________________ 776 777 void G4ReflectionFactory::CheckScale(const G4Scale3D& scale) const 778 { 779 // Check if scale correspond to fScale, 780 // if not give exception. 781 // --- 782 783 if (!IsReflection(scale)) return; 784 785 G4double diff = 0.; 786 for (auto i=0; i<4; ++i) 787 for (auto j=0; j<4; ++j) 788 diff += std::abs(scale(i,j) - fScale(i,j)); 789 790 if (diff > fScalePrecision) 791 { 792 std::ostringstream message; 793 message << "Unexpected scale in input !" << G4endl 794 << " Difference: " << diff; 795 G4Exception("G4ReflectionFactory::CheckScale()", 796 "GeomVol0002", FatalException, message); 797 } 798 } 799 800 //_____________________________________________________________________________ 801 802 G4VPVDivisionFactory* G4ReflectionFactory::GetPVDivisionFactory() const 803 { 804 // Returns the G4PVDivisionFactory instance if it exists, 805 // otherwise gives exception 806 // --- 807 808 G4VPVDivisionFactory* divisionFactory = G4VPVDivisionFactory::Instance(); 809 if (divisionFactory == nullptr) 810 { 811 std::ostringstream message; 812 message << "A concrete G4PVDivisionFactory instantiated is required !" 813 << G4endl 814 << " It has been requested to reflect divided volumes." 815 << G4endl 816 << " In this case, it is required to instantiate a concrete" 817 << G4endl 818 << " factory G4PVDivisionFactory in your program -before-" 819 << G4endl 820 << " executing the reflection !"; 821 G4Exception("G4ReflectionFactory::GetPVDivisionFactory()", 822 "GeomVol0002", FatalException, message); 823 } 824 825 return divisionFactory; 826 } 827 828 //_____________________________________________________________________________ 829 830 void G4ReflectionFactory::SetScalePrecision(G4double scaleValue) 831 { 832 fScalePrecision = scaleValue; 833 } 834 835 //_____________________________________________________________________________ 836 837 G4double G4ReflectionFactory::GetScalePrecision() const 838 { 839 return fScalePrecision; 840 } 841 842 //_____________________________________________________________________________ 843 844 void G4ReflectionFactory::SetVerboseLevel(G4int verboseLevel) 845 { 846 fVerboseLevel = verboseLevel; 847 } 848 849 //_____________________________________________________________________________ 850 851 G4int G4ReflectionFactory::GetVerboseLevel() const 852 { 853 return fVerboseLevel; 854 } 855 856 //_____________________________________________________________________________ 857 858 void G4ReflectionFactory::SetVolumesNameExtension(const G4String& nameExtension) 859 { 860 fNameExtension = nameExtension; 861 } 862 863 //_____________________________________________________________________________ 864 865 const G4String& G4ReflectionFactory::GetVolumesNameExtension() const 866 { 867 return fNameExtension; 868 } 869