00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 #include "G4ReflectionFactory.hh"
00057 #include "G4ReflectedSolid.hh"
00058 #include "G4Region.hh"
00059 #include "G4LogicalVolume.hh"
00060 #include "G4PVPlacement.hh"
00061 #include "G4PVReplica.hh"
00062 #include "G4VPVDivisionFactory.hh"
00063 #include "G4GeometryTolerance.hh"
00064
00065 G4ReflectionFactory* G4ReflectionFactory::fInstance = 0;
00066 const G4String G4ReflectionFactory::fDefaultNameExtension = "_refl";
00067 const G4Scale3D G4ReflectionFactory::fScale = G4ScaleZ3D(-1.0);
00068
00069
00070
00071 G4ReflectionFactory* G4ReflectionFactory::Instance()
00072 {
00073
00074
00075
00076 if (!fInstance) { fInstance = new G4ReflectionFactory(); }
00077
00078 return fInstance;
00079 }
00080
00081
00082
00083 G4ReflectionFactory::G4ReflectionFactory()
00084 : fVerboseLevel(0),
00085 fNameExtension(fDefaultNameExtension)
00086 {
00087
00088
00089
00090 fScalePrecision = 10.
00091 * G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
00092 fInstance = this;
00093 }
00094
00095
00096
00097 G4ReflectionFactory::~G4ReflectionFactory()
00098 {
00099 delete fInstance;
00100 }
00101
00102
00103
00104
00105
00106
00107
00108 G4PhysicalVolumesPair
00109 G4ReflectionFactory::Place( const G4Transform3D& transform3D,
00110 const G4String& name,
00111 G4LogicalVolume* LV,
00112 G4LogicalVolume* motherLV,
00113 G4bool isMany,
00114 G4int copyNo,
00115 G4bool surfCheck)
00116 {
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 if (fVerboseLevel>0)
00128 {
00129 G4cout << "Place " << name << " lv " << LV << " "
00130 << LV->GetName() << G4endl;
00131 }
00132
00133
00134 G4Scale3D scale;
00135 G4Rotate3D rotation;
00136 G4Translate3D translation;
00137
00138 transform3D.getDecomposition(scale, rotation, translation);
00139 G4Transform3D pureTransform3D = translation * rotation;
00140
00141
00142
00143
00144
00145
00146 CheckScale(scale);
00147
00148
00149
00150
00151
00152 if (! IsReflection(scale))
00153 {
00154 if (fVerboseLevel>0)
00155 G4cout << "Scale positive" << G4endl;
00156
00157 G4VPhysicalVolume* pv1
00158 = new G4PVPlacement(pureTransform3D, LV, name,
00159 motherLV, isMany, copyNo, surfCheck);
00160
00161 G4VPhysicalVolume* pv2 = 0;
00162 if (G4LogicalVolume* reflMotherLV = GetReflectedLV(motherLV))
00163 {
00164
00165
00166
00167 pv2 = new G4PVPlacement(fScale * (pureTransform3D * fScale.inverse()),
00168 ReflectLV(LV, surfCheck), name, reflMotherLV,
00169 isMany, copyNo, surfCheck);
00170 }
00171
00172 return G4PhysicalVolumesPair(pv1, pv2);
00173 }
00174
00175
00176
00177
00178
00179 if (fVerboseLevel>0)
00180 G4cout << "scale negative" << G4endl;
00181
00182 G4VPhysicalVolume* pv1
00183 = new G4PVPlacement(pureTransform3D, ReflectLV(LV, surfCheck), name,
00184 motherLV, isMany, copyNo, surfCheck);
00185
00186 G4VPhysicalVolume* pv2 = 0;
00187 if (G4LogicalVolume* reflMotherLV = GetReflectedLV(motherLV))
00188 {
00189
00190
00191
00192
00193 pv2 = new G4PVPlacement(fScale * (pureTransform3D * fScale.inverse()),
00194 LV, name, reflMotherLV, isMany, copyNo, surfCheck);
00195 }
00196
00197 return G4PhysicalVolumesPair(pv1, pv2);
00198 }
00199
00200
00201
00202
00203 G4PhysicalVolumesPair
00204 G4ReflectionFactory::Replicate(const G4String& name,
00205 G4LogicalVolume* LV,
00206 G4LogicalVolume* motherLV,
00207 EAxis axis,
00208 G4int nofReplicas,
00209 G4double width,
00210 G4double offset)
00211 {
00212
00213
00214
00215
00216
00217
00218 if (fVerboseLevel>0)
00219 {
00220 G4cout << "Replicate " << name << " lv " << LV << " "
00221 << LV->GetName() << G4endl;
00222 }
00223
00224 G4VPhysicalVolume* pv1
00225 = new G4PVReplica(name, LV, motherLV, axis, nofReplicas, width, offset);
00226
00227 G4VPhysicalVolume* pv2 = 0;
00228 if (G4LogicalVolume* reflMotherLV = GetReflectedLV(motherLV))
00229 {
00230
00231
00232
00233 pv2 = new G4PVReplica(name, ReflectLV(LV), reflMotherLV,
00234 axis, nofReplicas, width, offset);
00235 }
00236
00237 return G4PhysicalVolumesPair(pv1, pv2);
00238 }
00239
00240
00241
00242 G4PhysicalVolumesPair
00243 G4ReflectionFactory::Divide(const G4String& name,
00244 G4LogicalVolume* LV,
00245 G4LogicalVolume* motherLV,
00246 EAxis axis,
00247 G4int nofDivisions,
00248 G4double width,
00249 G4double offset)
00250 {
00251
00252
00253
00254
00255
00256
00257 if (fVerboseLevel>0)
00258 {
00259 G4cout << "Divide " << name << " lv " << LV << " "
00260 << LV->GetName() << G4endl;
00261 }
00262
00263 G4VPVDivisionFactory* divisionFactory = GetPVDivisionFactory();
00264
00265 G4VPhysicalVolume* pv1 = divisionFactory
00266 ->CreatePVDivision(name, LV, motherLV, axis, nofDivisions, width, offset);
00267
00268 G4VPhysicalVolume* pv2 = 0;
00269 if (G4LogicalVolume* reflMotherLV = GetReflectedLV(motherLV))
00270 {
00271
00272
00273
00274 pv2 = divisionFactory->CreatePVDivision(name, ReflectLV(LV), reflMotherLV,
00275 axis, nofDivisions, width, offset);
00276 }
00277
00278 return G4PhysicalVolumesPair(pv1, pv2);
00279 }
00280
00281
00282
00283
00284 G4PhysicalVolumesPair
00285 G4ReflectionFactory::Divide(const G4String& name,
00286 G4LogicalVolume* LV,
00287 G4LogicalVolume* motherLV,
00288 EAxis axis,
00289 G4int nofDivisions,
00290 G4double offset)
00291 {
00292
00293
00294
00295
00296
00297
00298 if (fVerboseLevel>0)
00299 {
00300 G4cout << "Divide " << name << " lv " << LV << " "
00301 << LV->GetName() << G4endl;
00302 }
00303
00304 G4VPVDivisionFactory* divisionFactory = GetPVDivisionFactory();
00305
00306 G4VPhysicalVolume* pv1 = divisionFactory
00307 ->CreatePVDivision(name, LV, motherLV, axis, nofDivisions, offset);
00308
00309 G4VPhysicalVolume* pv2 = 0;
00310 if (G4LogicalVolume* reflMotherLV = GetReflectedLV(motherLV))
00311 {
00312
00313
00314
00315 pv2 = divisionFactory->CreatePVDivision(name, ReflectLV(LV), reflMotherLV,
00316 axis, nofDivisions, offset);
00317 }
00318
00319 return G4PhysicalVolumesPair(pv1, pv2);
00320 }
00321
00322
00323
00324
00325 G4PhysicalVolumesPair
00326 G4ReflectionFactory::Divide(const G4String& name,
00327 G4LogicalVolume* LV,
00328 G4LogicalVolume* motherLV,
00329 EAxis axis,
00330 G4double width,
00331 G4double offset)
00332 {
00333
00334
00335
00336
00337
00338
00339 if (fVerboseLevel>0)
00340 {
00341 G4cout << "Divide " << name << " lv " << LV << " "
00342 << LV->GetName() << G4endl;
00343 }
00344
00345 G4VPVDivisionFactory* divisionFactory = GetPVDivisionFactory();
00346
00347 G4VPhysicalVolume* pv1 = divisionFactory
00348 -> CreatePVDivision(name, LV, motherLV, axis, width, offset);
00349
00350 G4VPhysicalVolume* pv2 = 0;
00351 if (G4LogicalVolume* reflMotherLV = GetReflectedLV(motherLV))
00352 {
00353
00354
00355
00356 pv2 = divisionFactory->CreatePVDivision(name, ReflectLV(LV), reflMotherLV,
00357 axis, width, offset);
00358 }
00359
00360 return G4PhysicalVolumesPair(pv1, pv2);
00361 }
00362
00363
00364
00365
00366
00367
00368
00369
00370 G4LogicalVolume* G4ReflectionFactory::ReflectLV(G4LogicalVolume* LV,
00371 G4bool surfCheck)
00372 {
00373
00374
00375
00376
00377 G4LogicalVolume* refLV = GetReflectedLV(LV);
00378
00379 if (!refLV)
00380 {
00381
00382
00383
00384 refLV = CreateReflectedLV(LV);
00385
00386
00387
00388 ReflectDaughters(LV, refLV, surfCheck);
00389
00390
00391
00392 if (LV->IsRootRegion())
00393 {
00394 LV->GetRegion()->AddRootLogicalVolume(refLV);
00395 }
00396 }
00397
00398 return refLV;
00399 }
00400
00401
00402
00403 G4LogicalVolume* G4ReflectionFactory::CreateReflectedLV(G4LogicalVolume* LV)
00404 {
00405
00406
00407
00408
00409
00410
00411 if (fReflectedLVMap.find(LV) != fReflectedLVMap.end())
00412 {
00413 std::ostringstream message;
00414 message << "Invalid reflection for volume: "
00415 << LV->GetName() << G4endl
00416 << "Cannot be applied to a volume already reflected !";
00417 G4Exception("G4ReflectionFactory::CreateReflectedLV()",
00418 "GeomVol0002", FatalException, message);
00419 }
00420
00421 G4VSolid* refSolid
00422 = new G4ReflectedSolid(LV->GetSolid()->GetName() + fNameExtension,
00423 LV->GetSolid(), fScale);
00424
00425 G4LogicalVolume* refLV
00426 = new G4LogicalVolume(refSolid,
00427 LV->GetMaterial(),
00428 LV->GetName() + fNameExtension,
00429 LV->GetFieldManager(),
00430 LV->GetSensitiveDetector(),
00431 LV->GetUserLimits());
00432 refLV->SetVisAttributes(LV->GetVisAttributes());
00433 refLV->SetBiasWeight(LV->GetBiasWeight());
00434 if (LV->IsRegion())
00435 {
00436 refLV->SetRegion(LV->GetRegion());
00437 }
00438
00439 fConstituentLVMap[LV] = refLV;
00440 fReflectedLVMap[refLV] = LV;
00441
00442 return refLV;
00443 }
00444
00445
00446
00447 void G4ReflectionFactory::ReflectDaughters(G4LogicalVolume* LV,
00448 G4LogicalVolume* refLV,
00449 G4bool surfCheck)
00450 {
00451
00452
00453
00454 if (fVerboseLevel>0)
00455 {
00456 G4cout << "G4ReflectionFactory::ReflectDaughters(): "
00457 << LV->GetNoDaughters() << " of " << LV->GetName() << G4endl;
00458 }
00459
00460 for (G4int i=0; i<LV->GetNoDaughters(); i++)
00461 {
00462 G4VPhysicalVolume* dPV = LV->GetDaughter(i);
00463
00464 if (! dPV->IsReplicated())
00465 {
00466 ReflectPVPlacement(dPV, refLV, surfCheck);
00467 }
00468 else if (! dPV->GetParameterisation())
00469 {
00470 ReflectPVReplica(dPV, refLV);
00471 }
00472 else if (G4VPVDivisionFactory::Instance() &&
00473 G4VPVDivisionFactory::Instance()->IsPVDivision(dPV))
00474 {
00475 ReflectPVDivision(dPV, refLV);
00476 }
00477 else
00478 {
00479 ReflectPVParameterised(dPV, refLV, surfCheck);
00480 }
00481 }
00482 }
00483
00484
00485
00486 void G4ReflectionFactory::ReflectPVPlacement(G4VPhysicalVolume* dPV,
00487 G4LogicalVolume* refLV,
00488 G4bool surfCheck)
00489 {
00490
00491
00492
00493
00494 G4LogicalVolume* dLV = dPV->GetLogicalVolume();
00495
00496
00497
00498 G4Transform3D dt(dPV->GetObjectRotationValue(), dPV->GetObjectTranslation());
00499 dt = fScale * (dt * fScale.inverse());
00500
00501 G4LogicalVolume* refDLV;
00502
00503 if (fVerboseLevel>0)
00504 G4cout << "Daughter: " << dPV << " " << dLV->GetName();
00505
00506 if (!IsReflected(dLV))
00507 {
00508
00509 if (fVerboseLevel>0)
00510 G4cout << " will be reflected." << G4endl;
00511
00512
00513 refDLV = GetReflectedLV(dLV);
00514
00515 if (!refDLV)
00516 {
00517
00518
00519 refDLV = CreateReflectedLV(dLV);
00520
00521
00522
00523 ReflectDaughters(dLV, refDLV, surfCheck);
00524 }
00525
00526
00527
00528
00529 new G4PVPlacement(dt, refDLV, dPV->GetName(), refLV,
00530 dPV->IsMany(), dPV->GetCopyNo(), surfCheck);
00531
00532 }
00533 else
00534 {
00535 if (fVerboseLevel>0)
00536 G4cout << " will be reconstitued." << G4endl;
00537
00538 refDLV = GetConstituentLV(dLV);
00539
00540 new G4PVPlacement(dt, refDLV, dPV->GetName(), refLV,
00541 dPV->IsMany(), dPV->GetCopyNo(), surfCheck);
00542 }
00543 }
00544
00545
00546
00547 void G4ReflectionFactory::ReflectPVReplica(G4VPhysicalVolume* dPV,
00548 G4LogicalVolume* refLV)
00549 {
00550
00551
00552
00553
00554 G4LogicalVolume* dLV = dPV->GetLogicalVolume();
00555
00556
00557
00558 EAxis axis;
00559 G4int nofReplicas;
00560 G4double width;
00561 G4double offset;
00562 G4bool consuming;
00563
00564 dPV->GetReplicationData(axis, nofReplicas, width, offset, consuming);
00565
00566 G4LogicalVolume* refDLV;
00567
00568 if (fVerboseLevel>0)
00569 G4cout << "Daughter: " << dPV << " " << dLV->GetName();
00570
00571 if (!IsReflected(dLV))
00572 {
00573 if (fVerboseLevel>0)
00574 G4cout << " will be reflected." << G4endl;
00575
00576
00577
00578 refDLV = GetReflectedLV(dLV);
00579
00580 if (!refDLV)
00581 {
00582
00583
00584 refDLV = CreateReflectedLV(dLV);
00585
00586
00587
00588 ReflectDaughters(dLV, refDLV);
00589 }
00590
00591
00592
00593 new G4PVReplica(dPV->GetName(), refDLV, refLV,
00594 axis, nofReplicas, width, offset);
00595 }
00596 else
00597 {
00598 if (fVerboseLevel>0)
00599 G4cout << " will be reconstitued." << G4endl;
00600
00601 refDLV = GetConstituentLV(dLV);
00602
00603 new G4PVReplica(dPV->GetName(), refDLV, refLV,
00604 axis, nofReplicas, width, offset);
00605 }
00606 }
00607
00608
00609
00610 void G4ReflectionFactory::ReflectPVDivision(G4VPhysicalVolume* dPV,
00611 G4LogicalVolume* refLV)
00612 {
00613
00614
00615
00616
00617 G4VPVDivisionFactory* divisionFactory = GetPVDivisionFactory();
00618
00619 G4LogicalVolume* dLV = dPV->GetLogicalVolume();
00620
00621
00622
00623 G4VPVParameterisation* param = dPV->GetParameterisation();
00624
00625 G4LogicalVolume* refDLV;
00626
00627 if (fVerboseLevel>0)
00628 G4cout << "Daughter: " << dPV << " " << dLV->GetName();
00629
00630 if (!IsReflected(dLV))
00631 {
00632 if (fVerboseLevel>0)
00633 G4cout << " will be reflected." << G4endl;
00634
00635
00636
00637 refDLV = GetReflectedLV(dLV);
00638
00639 if (!refDLV)
00640 {
00641
00642
00643 refDLV = CreateReflectedLV(dLV);
00644
00645
00646
00647 ReflectDaughters(dLV, refDLV);
00648 }
00649
00650
00651
00652 divisionFactory->CreatePVDivision(dPV->GetName(), refDLV, refLV, param);
00653 }
00654 else
00655 {
00656 if (fVerboseLevel>0)
00657 G4cout << " will be reconstitued." << G4endl;
00658
00659 refDLV = GetConstituentLV(dLV);
00660
00661 divisionFactory->CreatePVDivision(dPV->GetName(), refDLV, refLV, param);
00662 }
00663 }
00664
00665
00666
00667 void G4ReflectionFactory::ReflectPVParameterised(G4VPhysicalVolume* dPV,
00668 G4LogicalVolume*, G4bool)
00669 {
00670
00671
00672
00673
00674
00675 std::ostringstream message;
00676 message << "Not yet implemented. Volume: " << dPV->GetName() << G4endl
00677 << "Reflection of parameterised volumes is not yet implemented.";
00678 G4Exception("G4ReflectionFactory::ReflectPVParameterised()",
00679 "GeomVol0001", FatalException, message);
00680 }
00681
00682
00683
00684 G4LogicalVolume*
00685 G4ReflectionFactory::GetConstituentLV(G4LogicalVolume* reflLV) const
00686 {
00687
00688
00689
00690
00691 LogicalVolumesMapIterator it = fReflectedLVMap.find(reflLV);
00692
00693 if (it == fReflectedLVMap.end()) return 0;
00694
00695 return (*it).second;
00696 }
00697
00698
00699
00700 G4LogicalVolume*
00701 G4ReflectionFactory::GetReflectedLV(G4LogicalVolume* lv) const
00702 {
00703
00704
00705
00706
00707 LogicalVolumesMapIterator it = fConstituentLVMap.find(lv);
00708
00709 if (it == fConstituentLVMap.end()) return 0;
00710
00711 return (*it).second;
00712 }
00713
00714
00715
00716 G4bool G4ReflectionFactory::IsConstituent(G4LogicalVolume* lv) const
00717 {
00718
00719
00720
00721
00722 return (fConstituentLVMap.find(lv) != fConstituentLVMap.end());
00723 }
00724
00725
00726
00727 G4bool G4ReflectionFactory::IsReflected(G4LogicalVolume* lv) const
00728 {
00729
00730
00731
00732
00733 return (fReflectedLVMap.find(lv) != fReflectedLVMap.end());
00734 }
00735
00736
00737
00738 G4bool G4ReflectionFactory::IsReflection(const G4Scale3D& scale) const
00739 {
00740
00741
00742
00743 if (scale(0,0)*scale(1,1)*scale(2,2) < 0.)
00744 return true;
00745 else
00746 return false;
00747 }
00748
00749
00750
00751 const G4ReflectedVolumesMap&
00752 G4ReflectionFactory::GetReflectedVolumesMap() const
00753 {
00754 return fReflectedLVMap;
00755 }
00756
00757
00758
00759 void
00760 G4ReflectionFactory::Reset()
00761 {
00762 fConstituentLVMap.~map();
00763 fReflectedLVMap.~map();
00764 }
00765
00766
00767
00768 void G4ReflectionFactory::PrintConstituentLVMap()
00769 {
00770
00771
00772
00773 LogicalVolumesMapIterator it;
00774 for (it = fConstituentLVMap.begin(); it != fConstituentLVMap.end(); it++)
00775 {
00776 G4cout << "lv: " << (*it).first << " lv_refl: " << (*it).second << G4endl;
00777 }
00778 G4cout << G4endl;
00779 }
00780
00781
00782
00783 void G4ReflectionFactory::CheckScale(const G4Scale3D& scale) const
00784 {
00785
00786
00787
00788
00789 if (!IsReflection(scale)) return;
00790
00791 G4double diff = 0.;
00792 for (G4int i=0; i<4; i++)
00793 for (G4int j=0; j<4; j++)
00794 diff += std::abs(scale(i,j) - fScale(i,j));
00795
00796 if (diff > fScalePrecision)
00797 {
00798 std::ostringstream message;
00799 message << "Unexpected scale in input !" << G4endl
00800 << " Difference: " << diff;
00801 G4Exception("G4ReflectionFactory::CheckScale()",
00802 "GeomVol0002", FatalException, message);
00803 }
00804 }
00805
00806
00807
00808 G4VPVDivisionFactory* G4ReflectionFactory::GetPVDivisionFactory() const
00809 {
00810
00811
00812
00813
00814 G4VPVDivisionFactory* divisionFactory = G4VPVDivisionFactory::Instance();
00815 if (!divisionFactory)
00816 {
00817 std::ostringstream message;
00818 message << "A concrete G4PVDivisionFactory instantiated is required !"
00819 << G4endl
00820 << " It has been requested to reflect divided volumes."
00821 << G4endl
00822 << " In this case, it is required to instantiate a concrete"
00823 << G4endl
00824 << " factory G4PVDivisionFactory in your program -before-"
00825 << G4endl
00826 << " executing the reflection !";
00827 G4Exception("G4ReflectionFactory::GetPVDivisionFactory()",
00828 "GeomVol0002", FatalException, message);
00829 }
00830
00831 return divisionFactory;
00832 }
00833
00834
00835
00836 void G4ReflectionFactory::SetScalePrecision(G4double scaleValue)
00837 {
00838 fScalePrecision = scaleValue;
00839 }
00840
00841
00842
00843 G4double G4ReflectionFactory::GetScalePrecision() const
00844 {
00845 return fScalePrecision;
00846 }
00847
00848
00849
00850 void G4ReflectionFactory::SetVerboseLevel(G4int verboseLevel)
00851 {
00852 fVerboseLevel = verboseLevel;
00853 }
00854
00855
00856
00857 G4int G4ReflectionFactory::GetVerboseLevel() const
00858 {
00859 return fVerboseLevel;
00860 }
00861
00862
00863
00864 void G4ReflectionFactory::SetVolumesNameExtension(const G4String& nameExtension)
00865 {
00866 fNameExtension = nameExtension;
00867 }
00868
00869
00870
00871 const G4String& G4ReflectionFactory::GetVolumesNameExtension() const
00872 {
00873 return fNameExtension;
00874 }
00875
00876
00877
00878
00879
00880
00881
00882
00883