Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/examples/extended/optical/wls/src/WLSDetectorConstruction.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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 //
 27 /// \file optical/wls/src/WLSDetectorConstruction.cc
 28 /// \brief Implementation of the WLSDetectorConstruction class
 29 //
 30 //
 31 
 32 #include "WLSDetectorConstruction.hh"
 33 
 34 #include "WLSDetectorMessenger.hh"
 35 #include "WLSMaterials.hh"
 36 #include "WLSPhotonDetSD.hh"
 37 
 38 #include "G4Box.hh"
 39 #include "G4Colour.hh"
 40 #include "G4EllipticalTube.hh"
 41 #include "G4GeometryManager.hh"
 42 #include "G4LogicalBorderSurface.hh"
 43 #include "G4LogicalSkinSurface.hh"
 44 #include "G4LogicalVolume.hh"
 45 #include "G4LogicalVolumeStore.hh"
 46 #include "G4Material.hh"
 47 #include "G4NistManager.hh"
 48 #include "G4OpticalSurface.hh"
 49 #include "G4PVPlacement.hh"
 50 #include "G4PhysicalConstants.hh"
 51 #include "G4PhysicalVolumeStore.hh"
 52 #include "G4RunManager.hh"
 53 #include "G4SDManager.hh"
 54 #include "G4SolidStore.hh"
 55 #include "G4SystemOfUnits.hh"
 56 #include "G4Tubs.hh"
 57 #include "G4UserLimits.hh"
 58 #include "G4VisAttributes.hh"
 59 #include "G4ios.hh"
 60 #include "globals.hh"
 61 
 62 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 63 
 64 WLSDetectorConstruction::WLSDetectorConstruction() : fVisAttributes()
 65 {
 66   fDetectorMessenger = new WLSDetectorMessenger(this);
 67 
 68   fMPPCHalfL = fWLSfiberRY;
 69   fClrfiberZ = fMPPCZ + 10. * nm;
 70   fHoleLength = fBarLength;
 71 }
 72 
 73 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 74 
 75 WLSDetectorConstruction::~WLSDetectorConstruction()
 76 {
 77   delete fDetectorMessenger;
 78   delete fMaterials;
 79   for (auto visAttributes : fVisAttributes) {
 80     delete visAttributes;
 81   }
 82 }
 83 
 84 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 85 
 86 G4VPhysicalVolume* WLSDetectorConstruction::Construct()
 87 {
 88   if (fPhysiWorld) {
 89     G4GeometryManager::GetInstance()->OpenGeometry();
 90     G4PhysicalVolumeStore::GetInstance()->Clean();
 91     G4LogicalVolumeStore::GetInstance()->Clean();
 92     G4SolidStore::GetInstance()->Clean();
 93     G4LogicalSkinSurface::CleanSurfaceTable();
 94     G4LogicalBorderSurface::CleanSurfaceTable();
 95   }
 96 
 97   fMaterials = WLSMaterials::GetInstance();
 98   UpdateGeometryParameters();
 99 
100   return ConstructDetector();
101 }
102 
103 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
104 
105 G4VPhysicalVolume* WLSDetectorConstruction::ConstructDetector()
106 {
107   auto air = FindMaterial("G4_AIR");
108   // G4cout << "\nMaterial Properties Table for G4_AIR:" << G4endl;
109   // air->GetMaterialPropertiesTable()->DumpTable();
110 
111   //--------------------------------------------------
112   // World
113   //--------------------------------------------------
114 
115   G4VSolid* solidWorld = new G4Box("World", fWorldSizeX, fWorldSizeY, fWorldSizeZ);
116 
117   fLogicWorld = new G4LogicalVolume(solidWorld, air, "World");
118 
119   fPhysiWorld =
120     new G4PVPlacement(nullptr, G4ThreeVector(), fLogicWorld, "World", nullptr, false, 0);
121 
122   //--------------------------------------------------
123   // Extrusion
124   //--------------------------------------------------
125 
126   auto coating = FindMaterial("Coating");
127 
128   G4VSolid* solidExtrusion =
129     new G4Box("Extrusion", GetBarBase() / 2., GetBarBase() / 2., GetBarLength() / 2.);
130 
131   auto logicExtrusion = new G4LogicalVolume(solidExtrusion, coating, "Extrusion");
132 
133   auto TiO2Surface =
134     new G4OpticalSurface("TiO2Surface", glisur, ground, dielectric_metal, fExtrusionPolish);
135 
136   auto TiO2SurfaceProperty = new G4MaterialPropertiesTable();
137 
138   std::vector<G4double> p_TiO2 = {2.00 * eV, 3.47 * eV};
139 
140   std::vector<G4double> refl_TiO2 = {fExtrusionReflectivity, fExtrusionReflectivity};
141   std::vector<G4double> effi_TiO2 = {0., 0.};
142 
143   TiO2SurfaceProperty->AddProperty("REFLECTIVITY", p_TiO2, refl_TiO2);
144   TiO2SurfaceProperty->AddProperty("EFFICIENCY", p_TiO2, effi_TiO2);
145 
146   TiO2Surface->SetMaterialPropertiesTable(TiO2SurfaceProperty);
147 
148   new G4PVPlacement(nullptr, G4ThreeVector(), logicExtrusion, "Extrusion", fLogicWorld, false, 0);
149 
150   new G4LogicalSkinSurface("TiO2Surface", logicExtrusion, TiO2Surface);
151 
152   //--------------------------------------------------
153   // Scintillator
154   //--------------------------------------------------
155 
156   auto polystyrene = FindMaterial("Polystyrene");
157   // G4cout << "\nMaterial Properties Table for Polystyrene:" << G4endl;
158   // polystyrene->GetMaterialPropertiesTable()->DumpTable();
159 
160   G4VSolid* solidScintillator =
161     new G4Box("Scintillator", GetBarBase() / 2. - GetCoatingThickness() - GetCoatingRadius(),
162               GetBarBase() / 2. - GetCoatingThickness() - GetCoatingRadius(), GetBarLength() / 2.);
163 
164   auto logicScintillator = new G4LogicalVolume(solidScintillator, polystyrene, "Scintillator");
165 
166   new G4PVPlacement(nullptr, G4ThreeVector(), logicScintillator, "Scintillator", logicExtrusion,
167                     false, 0);
168 
169   G4LogicalVolume* logicScintSide = nullptr;
170   G4LogicalVolume* logicScintCrnr = nullptr;
171   if (GetCoatingRadius() > 0.) {
172     G4VSolid* solidScintside =
173       new G4Box("SideOfBar", GetBarBase() / 2. - GetCoatingThickness() - GetCoatingRadius(),
174                 GetCoatingRadius() / 2., GetBarLength() / 2.);
175 
176     G4VSolid* solidScintcrnr = new G4Tubs("CrnrOfBar", 0.0 * cm, GetCoatingRadius(),
177                                           GetBarLength() / 2., 0. * deg, 90. * deg);
178 
179     logicScintSide = new G4LogicalVolume(solidScintside, polystyrene, "SideOfBar");
180 
181     logicScintCrnr = new G4LogicalVolume(solidScintcrnr, polystyrene, "CrnrOfBar");
182 
183     G4double pos = GetBarBase() / 2. - GetCoatingThickness() - GetCoatingRadius() / 2.;
184 
185     new G4PVPlacement(nullptr, G4ThreeVector(0., -pos, 0.), logicScintSide, "SideOfBar",
186                       logicExtrusion, false, 0);
187 
188     new G4PVPlacement(nullptr, G4ThreeVector(0., pos, 0.), logicScintSide, "SideOfBar",
189                       logicExtrusion, false, 1);
190 
191     auto rot1 = new G4RotationMatrix();
192     rot1->rotateZ(-90. * deg);
193 
194     new G4PVPlacement(rot1, G4ThreeVector(pos, 0., 0.), logicScintSide, "SideOfBar", logicExtrusion,
195                       false, 2);
196 
197     new G4PVPlacement(rot1, G4ThreeVector(-pos, 0., 0.), logicScintSide, "SideOfBar",
198                       logicExtrusion, false, 3);
199 
200     pos = GetBarBase() / 2. - GetCoatingThickness() - GetCoatingRadius();
201 
202     new G4PVPlacement(nullptr, G4ThreeVector(pos, pos, 0.), logicScintCrnr, "CrnrOfBar",
203                       logicExtrusion, false, 0);
204 
205     new G4PVPlacement(rot1, G4ThreeVector(-pos, pos, 0.), logicScintCrnr, "CrnrOfBar",
206                       logicExtrusion, false, 1);
207 
208     auto rot2 = new G4RotationMatrix();
209     rot2->rotateZ(-180. * deg);
210 
211     new G4PVPlacement(rot2, G4ThreeVector(-pos, -pos, 0.), logicScintCrnr, "CrnrOfBar",
212                       logicExtrusion, false, 2);
213 
214     auto rot3 = new G4RotationMatrix();
215     rot3->rotateZ(-270. * deg);
216 
217     new G4PVPlacement(rot3, G4ThreeVector(pos, -pos, 0.), logicScintCrnr, "CrnrOfBar",
218                       logicExtrusion, false, 3);
219   }
220 
221   if (GetFiberRadius() < GetHoleRadius()) {
222     G4VSolid* solidHole =
223       new G4Tubs("Hole", 0., GetHoleRadius(), GetHoleLength() / 2., 0. * deg, 360. * deg);
224 
225     fLogicHole = new G4LogicalVolume(solidHole, air, "Hole");
226 
227     fPhysiHole =
228       new G4PVPlacement(nullptr, G4ThreeVector(), fLogicHole, "Hole", logicScintillator, false, 0);
229   }
230 
231   //--------------------------------------------------
232   // Fiber
233   //--------------------------------------------------
234 
235   if (!(fLogicHole) || !(fPhysiHole)) {
236     G4ExceptionDescription ed;
237     ed << "The Fiber Hole has not been constructed";
238     G4Exception("WLSDetectorConstruction", "wls001", FatalException, ed);
239   }
240 
241   // Pointers to the most recently constructed volume
242   G4LogicalVolume* logicPlacement = fLogicHole;
243   G4VPhysicalVolume* physiPlacement = fPhysiHole;
244 
245   //--------------------------------------------------
246   // Fiber Construction
247   //--------------------------------------------------
248 
249   // Boundary Surface Properties
250   G4OpticalSurface* opSurface = nullptr;
251 
252   if (fSurfaceRoughness < 1.)
253     opSurface = new G4OpticalSurface("RoughSurface", glisur, ground, dielectric_dielectric,
254                                      fSurfaceRoughness);
255 
256   G4LogicalVolume* logicWLSfiber = nullptr;
257   G4LogicalVolume* logicClad1 = nullptr;
258   G4LogicalVolume* logicClad2 = nullptr;
259   G4VPhysicalVolume* physiClad1 = nullptr;
260   G4VPhysicalVolume* physiClad2 = nullptr;
261 
262   auto fpethylene = FindMaterial("FPethylene");
263   auto pethylene = FindMaterial("Pethylene");
264   auto pmma = FindMaterial("PMMA");
265 
266   // Determine the number of cladding layers to be built
267   switch (fNumOfCladLayers) {
268     case 2:
269 
270       //--------------------------------------------------
271       // Cladding 2
272       //--------------------------------------------------
273 
274       // G4cout << "\nMaterial Properties Table for fPethylene:" << G4endl;
275       // fpethylene->GetMaterialPropertiesTable()->DumpTable();
276 
277       G4VSolid* solidClad2;
278 
279       if (fXYRatio == 1.)
280         solidClad2 = new G4Tubs("Clad2", 0., fClad2RX, fClad2Z, 0., twopi);
281       else
282         solidClad2 = new G4EllipticalTube("Clad2", fClad2RX, fClad2RY, fClad2Z);
283 
284       logicClad2 = new G4LogicalVolume(solidClad2, fpethylene, "Clad2");
285 
286       physiClad2 = new G4PVPlacement(nullptr, G4ThreeVector(0.0, 0.0, fWLSfiberOrigin), logicClad2,
287                                      "Clad2", logicPlacement, false, 0);
288 
289       // Place the rough surface only if needed
290       if (opSurface) {
291         new G4LogicalBorderSurface("surfaceClad2Out", physiClad2, physiPlacement, opSurface);
292         new G4LogicalBorderSurface("surfaceClad2In", physiPlacement, physiClad2, opSurface);
293       }
294 
295       logicPlacement = logicClad2;
296       physiPlacement = physiClad2;
297       [[fallthrough]];
298 
299     case 1:
300 
301       //--------------------------------------------------
302       // Cladding 1
303       //--------------------------------------------------
304 
305       // G4cout << "\nMaterial Properties Table for Pethylene:" << G4endl;
306       // pethylene->GetMaterialPropertiesTable()->DumpTable();
307 
308       G4VSolid* solidClad1;
309 
310       if (fXYRatio == 1.)
311         solidClad1 = new G4Tubs("Clad1", 0., fClad1RX, fClad1Z, 0., twopi);
312       else
313         solidClad1 = new G4EllipticalTube("Clad1", fClad1RX, fClad1RY, fClad1Z);
314 
315       logicClad1 = new G4LogicalVolume(solidClad1, pethylene, "Clad1");
316 
317       physiClad1 = new G4PVPlacement(nullptr, G4ThreeVector(0., 0., fWLSfiberOrigin), logicClad1,
318                                      "Clad1", logicPlacement, false, 0);
319 
320       // Place the rough surface only if needed
321       if (opSurface) {
322         new G4LogicalBorderSurface("surfaceClad1Out", physiClad1, physiPlacement, opSurface);
323 
324         new G4LogicalBorderSurface("surfaceClad1In", physiPlacement, physiClad1, opSurface);
325       }
326 
327       logicPlacement = logicClad1;
328       physiPlacement = physiClad1;
329       [[fallthrough]];
330 
331     default:
332 
333       //--------------------------------------------------
334       // WLS Fiber
335       //--------------------------------------------------
336 
337       // G4cout << "\nMaterial Properties Table for PMMA:" << G4endl;
338       // pmma->GetMaterialPropertiesTable()->DumpTable();
339 
340       G4VSolid* solidWLSfiber;
341 
342       if (fXYRatio == 1.) {
343         solidWLSfiber = new G4Tubs("WLSFiber", 0., fWLSfiberRX, fWLSfiberZ, 0., twopi);
344       }
345       else {
346         solidWLSfiber = new G4EllipticalTube("WLSFiber", fWLSfiberRX, fWLSfiberRY, fWLSfiberZ);
347       }
348 
349       logicWLSfiber = new G4LogicalVolume(solidWLSfiber, pmma, "WLSFiber");
350 
351       logicWLSfiber->SetUserLimits(new G4UserLimits(DBL_MAX, DBL_MAX, 10. * ms));
352 
353       G4VPhysicalVolume* physiWLSfiber =
354         new G4PVPlacement(nullptr, G4ThreeVector(0., 0., fWLSfiberOrigin), logicWLSfiber,
355                           "WLSFiber", logicPlacement, false, 0);
356 
357       // Place the rough surface only if needed
358       if (opSurface) {
359         new G4LogicalBorderSurface("surfaceWLSOut", physiWLSfiber, physiPlacement, opSurface);
360 
361         new G4LogicalBorderSurface("surfaceWLSIn", physiPlacement, physiWLSfiber, opSurface);
362       }
363   }
364 
365   //--------------------------------------------------
366   // Mirror for reflection at one of the end
367   //--------------------------------------------------
368 
369   // Place the mirror only if the user wants the mirror
370   G4LogicalVolume* logicMirror = nullptr;
371 
372   auto aluminum = FindMaterial("G4_Al");
373 
374   if (fMirrorToggle) {
375     G4VSolid* solidMirror = new G4Box("Mirror", fMirrorRmax, fMirrorRmax, fMirrorZ);
376 
377     logicMirror = new G4LogicalVolume(solidMirror, aluminum, "Mirror");
378 
379     auto mirrorSurface =
380       new G4OpticalSurface("MirrorSurface", glisur, ground, dielectric_metal, fMirrorPolish);
381 
382     auto mirrorSurfaceProperty = new G4MaterialPropertiesTable();
383 
384     std::vector<G4double> p_mirror = {2.00 * eV, 3.47 * eV};
385     std::vector<G4double> refl_mirror = {fMirrorReflectivity, fMirrorReflectivity};
386     std::vector<G4double> effi_mirror = {0., 0.};
387 
388     mirrorSurfaceProperty->AddProperty("REFLECTIVITY", p_mirror, refl_mirror);
389     mirrorSurfaceProperty->AddProperty("EFFICIENCY", p_mirror, effi_mirror);
390 
391     mirrorSurface->SetMaterialPropertiesTable(mirrorSurfaceProperty);
392 
393     new G4PVPlacement(nullptr, G4ThreeVector(0., 0., fMirrorOrigin), logicMirror, "Mirror",
394                       fLogicWorld, false, 0);
395 
396     new G4LogicalSkinSurface("MirrorSurface", logicMirror, mirrorSurface);
397   }
398 
399   //--------------------------------------------------
400   // Coupling at the read-out end
401   //--------------------------------------------------
402 
403   // Clear Fiber (Coupling Layer)
404   G4VSolid* solidCouple = new G4Box("Couple", fCoupleRX, fCoupleRY, fCoupleZ);
405 
406   auto logicCouple = new G4LogicalVolume(solidCouple, air, "Couple");
407 
408   new G4PVPlacement(nullptr, G4ThreeVector(0., 0., fCoupleOrigin), logicCouple, "Couple",
409                     fLogicWorld, false, 0);
410 
411   //--------------------------------------------------
412   // A logical layer in front of PhotonDet
413   //--------------------------------------------------
414 
415   // Purpose: Preventing direct dielectric to metal contact
416 
417   // Check for valid placement of PhotonDet
418   if (fMPPCTheta > std::atan(fMPPCDist / fMPPCHalfL)) {
419     fMPPCTheta = 0.;
420     fMPPCOriginX = std::sin(fMPPCTheta) * (fMPPCDist + fClrfiberZ);
421     fMPPCOriginZ = -fCoupleZ + std::cos(fMPPCTheta) * (fMPPCDist + fClrfiberZ);
422     G4ExceptionDescription ed;
423     ed << "Invalid alignment.  Alignment reset to 0.";
424     G4Exception("WLSDetectorConstruction", "wls002", JustWarning, ed);
425   }
426 
427   // Clear Fiber (Coupling Layer)
428   G4VSolid* solidClrfiber;
429 
430   if (fMPPCShape == "Square") {
431     solidClrfiber = new G4Box("ClearFiber", fClrfiberHalfL, fClrfiberHalfL, fClrfiberZ);
432   }
433   else {
434     solidClrfiber = new G4Tubs("ClearFiber", 0., fClrfiberHalfL, fClrfiberZ, 0., twopi);
435   }
436 
437   auto logicClrfiber = new G4LogicalVolume(solidClrfiber, air, "ClearFiber");
438 
439   new G4PVPlacement(new G4RotationMatrix(CLHEP::HepRotationY(-fMPPCTheta)),
440                     G4ThreeVector(fMPPCOriginX, 0.0, fMPPCOriginZ), logicClrfiber, "ClearFiber",
441                     logicCouple, false, 0);
442 
443   //--------------------------------------------------
444   // PhotonDet (Sensitive Detector)
445   //--------------------------------------------------
446 
447   // Physical Construction
448   G4VSolid* solidPhotonDet = nullptr;
449 
450   if (fMPPCShape == "Square")
451     solidPhotonDet = new G4Box("PhotonDet", fMPPCHalfL, fMPPCHalfL, fMPPCZ);
452   else
453     solidPhotonDet = new G4Tubs("PhotonDet", 0., fMPPCHalfL, fMPPCZ, 0., twopi);
454 
455   auto logicPhotonDet = new G4LogicalVolume(solidPhotonDet, aluminum, "PhotonDet_LV");
456 
457   new G4PVPlacement(nullptr, G4ThreeVector(0., 0., 0.), logicPhotonDet, "PhotonDet", logicClrfiber,
458                     false, 0);
459 
460   // PhotonDet Surface Properties
461   auto photonDetSurface =
462     new G4OpticalSurface("PhotonDetSurface", glisur, ground, dielectric_metal, fMPPCPolish);
463 
464   auto photonDetSurfaceProperty = new G4MaterialPropertiesTable();
465 
466   std::vector<G4double> p_mppc = {2.00 * eV, 3.47 * eV};
467   std::vector<G4double> refl_mppc = {fMPPCReflectivity, fMPPCReflectivity};
468   std::vector<G4double> effi_mppc = {1., 1.};
469 
470   photonDetSurfaceProperty->AddProperty("REFLECTIVITY", p_mppc, refl_mppc);
471   photonDetSurfaceProperty->AddProperty("EFFICIENCY", p_mppc, effi_mppc);
472 
473   photonDetSurface->SetMaterialPropertiesTable(photonDetSurfaceProperty);
474 
475   new G4LogicalSkinSurface("PhotonDetSurface", logicPhotonDet, photonDetSurface);
476 
477   // visualization attributes -------------------------------------------------
478 
479   auto visAttributes = new G4VisAttributes(G4Colour(1.0, 1.0, 1.0));
480   visAttributes->SetVisibility(false);
481   fLogicWorld->SetVisAttributes(visAttributes);
482   fVisAttributes.push_back(visAttributes);
483 
484   visAttributes = new G4VisAttributes(G4Colour(0.2, 0.2, 0.2, 0.5));
485   visAttributes->SetVisibility(true);
486   logicExtrusion->SetVisAttributes(visAttributes);
487   fVisAttributes.push_back(visAttributes);
488 
489   visAttributes = new G4VisAttributes(G4Colour(0.0, 0.0, 1.0, 0.9));
490   visAttributes->SetVisibility(true);
491   logicScintillator->SetVisAttributes(visAttributes);
492   fVisAttributes.push_back(visAttributes);
493 
494   visAttributes = new G4VisAttributes(G4Colour(0.0, 0.8, 0.2, 0.2));
495   visAttributes->SetVisibility(true);
496   logicScintSide->SetVisAttributes(visAttributes);
497   fVisAttributes.push_back(visAttributes);
498 
499   visAttributes = new G4VisAttributes(G4Colour(0.0, 0.8, 0.2, 0.2));
500   visAttributes->SetVisibility(true);
501   logicScintCrnr->SetVisAttributes(visAttributes);
502   fVisAttributes.push_back(visAttributes);
503 
504   visAttributes = new G4VisAttributes(G4Colour(0.4, 0.0, 0.0, 0.5));
505   visAttributes->SetVisibility(true);
506   fLogicHole->SetVisAttributes(visAttributes);
507   fVisAttributes.push_back(visAttributes);
508 
509   if (logicClad1 != nullptr) {
510     visAttributes = new G4VisAttributes(G4Colour(0.0, 0.8, 0.5, 0.5));
511     visAttributes->SetVisibility(true);
512     logicClad1->SetVisAttributes(visAttributes);
513     fVisAttributes.push_back(visAttributes);
514   }
515 
516   if (logicClad2 != nullptr) {
517     visAttributes = new G4VisAttributes(G4Colour(0.0, 0.5, 0.8, 0.5));
518     visAttributes->SetVisibility(true);
519     logicClad2->SetVisAttributes(visAttributes);
520     fVisAttributes.push_back(visAttributes);
521   }
522 
523   visAttributes = new G4VisAttributes(G4Colour(0.8, 0.8, 1.0));
524   visAttributes->SetVisibility(true);
525   logicWLSfiber->SetVisAttributes(visAttributes);
526   fVisAttributes.push_back(visAttributes);
527 
528   if (fMirrorToggle == true) {
529     visAttributes = new G4VisAttributes(G4Colour(0.3, 0.3, 1.0, 0.3));
530     visAttributes->SetVisibility(true);
531     logicMirror->SetVisAttributes(visAttributes);
532     fVisAttributes.push_back(visAttributes);
533   }
534 
535   visAttributes = new G4VisAttributes(G4Colour(0.0, 0.0, 0.5, 0.5));
536   visAttributes->SetVisibility(true);
537   logicCouple->SetVisAttributes(visAttributes);
538   fVisAttributes.push_back(visAttributes);
539 
540   visAttributes = new G4VisAttributes(G4Colour(0.3, 0.3, 0.3, 0.5));
541   visAttributes->SetVisibility(true);
542   logicClrfiber->SetVisAttributes(visAttributes);
543   fVisAttributes.push_back(visAttributes);
544 
545   visAttributes = new G4VisAttributes(G4Colour(1.0, 1.0, 1.0, 0.8));
546   visAttributes->SetVisibility(true);
547   logicPhotonDet->SetVisAttributes(visAttributes);
548   fVisAttributes.push_back(visAttributes);
549 
550   return fPhysiWorld;
551 }
552 
553 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
554 
555 void WLSDetectorConstruction::ConstructSDandField()
556 {
557   if (!fmppcSD.Get()) {
558     G4String mppcSDName = "WLS/PhotonDet";
559     auto mppcSD = new WLSPhotonDetSD(mppcSDName);
560     G4SDManager::GetSDMpointer()->AddNewDetector(mppcSD);
561     fmppcSD.Put(mppcSD);
562   }
563   SetSensitiveDetector("PhotonDet_LV", fmppcSD.Get(), true);
564 }
565 
566 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
567 
568 void WLSDetectorConstruction::UpdateGeometryParameters()
569 {
570   fWLSfiberRX = fXYRatio * fWLSfiberRY;
571 
572   fClad1RX = fWLSfiberRX + 0.03 * fWLSfiberRX;
573   fClad1RY = fWLSfiberRY + 0.03 * fWLSfiberRY;
574   fClad1Z = fWLSfiberZ;
575 
576   fClad2RX = fClad1RX + 0.03 * fWLSfiberRX;
577   fClad2RY = fClad1RY + 0.03 * fWLSfiberRY;
578   fClad2Z = fWLSfiberZ;
579 
580   fWorldSizeX = fClad2RX + fMPPCDist + fMPPCHalfL + 1. * cm;
581   fWorldSizeY = fClad2RY + fMPPCDist + fMPPCHalfL + 1. * cm;
582   fWorldSizeZ = fWLSfiberZ + fMPPCDist + fMPPCHalfL + 1. * cm;
583 
584   fCoupleRX = fWorldSizeX;
585   fCoupleRY = fWorldSizeY;
586   fCoupleZ = (fWorldSizeZ - fWLSfiberZ) / 2.;
587 
588   fClrfiberHalfL = fMPPCHalfL;
589 
590   fMirrorRmax = fClad2RY;
591 
592   fCoupleOrigin = fWLSfiberOrigin + fWLSfiberZ + fCoupleZ;
593   fMirrorOrigin = fWLSfiberOrigin - fWLSfiberZ - fMirrorZ;
594   fMPPCOriginX = std::sin(fMPPCTheta) * (fMPPCDist + fClrfiberZ);
595   fMPPCOriginZ = -fCoupleZ + std::cos(fMPPCTheta) * (fMPPCDist + fClrfiberZ);
596 }
597 
598 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
599 
600 void WLSDetectorConstruction::SetPhotonDetGeometry(G4String shape)
601 // Set the Geometry of the PhotonDet detector
602 // Pre:  shape must be either "Circle" and "Square"
603 {
604   if (shape == "Circle" || shape == "Square") fMPPCShape = shape;
605   G4RunManager::GetRunManager()->GeometryHasBeenModified();
606 }
607 
608 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
609 
610 void WLSDetectorConstruction::SetNumberOfCladding(G4int num)
611 // Set the number of claddings
612 // Pre: 0 <= num <= 2
613 {
614   fNumOfCladLayers = num;
615   G4RunManager::GetRunManager()->GeometryHasBeenModified();
616 }
617 
618 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
619 
620 void WLSDetectorConstruction::SetWLSLength(G4double length)
621 // Set the TOTAL length of the WLS fiber
622 {
623   fWLSfiberZ = length;
624   G4RunManager::GetRunManager()->GeometryHasBeenModified();
625 }
626 
627 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
628 
629 void WLSDetectorConstruction::SetWLSRadius(G4double radius)
630 // Set the Y radius of WLS fiber
631 {
632   fWLSfiberRY = radius;
633   G4RunManager::GetRunManager()->GeometryHasBeenModified();
634 }
635 
636 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
637 
638 void WLSDetectorConstruction::SetClad1Radius(G4double radius)
639 // Set the Y radius of Cladding 1
640 {
641   fClad1RY = radius;
642   G4RunManager::GetRunManager()->GeometryHasBeenModified();
643 }
644 
645 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
646 
647 void WLSDetectorConstruction::SetClad2Radius(G4double radius)
648 // Set the Y radius of Cladding 2
649 {
650   fClad2RY = radius;
651   G4RunManager::GetRunManager()->GeometryHasBeenModified();
652 }
653 
654 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
655 
656 void WLSDetectorConstruction::SetPhotonDetHalfLength(G4double halfL)
657 // Set the half length of the PhotonDet detector
658 // The half length will be the radius if PhotonDet is circular
659 {
660   fMPPCHalfL = halfL;
661   G4RunManager::GetRunManager()->GeometryHasBeenModified();
662 }
663 
664 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
665 
666 void WLSDetectorConstruction::SetGap(G4double gap)
667 // Set the distance between fiber end and PhotonDet
668 {
669   fMPPCDist = gap;
670   G4RunManager::GetRunManager()->GeometryHasBeenModified();
671 }
672 
673 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
674 
675 void WLSDetectorConstruction::SetPhotonDetAlignment(G4double theta)
676 // Set the Aligment of PhotonDet with respect to the z axis
677 // If theta is 0 deg, then the detector is perfectly aligned
678 // PhotonDet will be deviated by theta from z axis
679 // facing towards the center of the fiber
680 {
681   fMPPCTheta = theta;
682   G4RunManager::GetRunManager()->GeometryHasBeenModified();
683 }
684 
685 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
686 
687 void WLSDetectorConstruction::SetSurfaceRoughness(G4double roughness)
688 // Set the Surface Roughness between Cladding 1 and WLS fiber
689 // Pre: 0 < roughness <= 1
690 {
691   fSurfaceRoughness = roughness;
692   G4RunManager::GetRunManager()->GeometryHasBeenModified();
693 }
694 
695 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
696 
697 void WLSDetectorConstruction::SetMirrorPolish(G4double polish)
698 // Set the Polish of the mirror, polish of 1 is a perfect mirror surface
699 // Pre: 0 < polish <= 1
700 {
701   fMirrorPolish = polish;
702   G4RunManager::GetRunManager()->GeometryHasBeenModified();
703 }
704 
705 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
706 
707 void WLSDetectorConstruction::SetMirrorReflectivity(G4double reflectivity)
708 // Set the Reflectivity of the mirror, reflectivity of 1 is a perfect mirror
709 // Pre: 0 < reflectivity <= 1
710 {
711   fMirrorReflectivity = reflectivity;
712   G4RunManager::GetRunManager()->GeometryHasBeenModified();
713 }
714 
715 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
716 
717 void WLSDetectorConstruction::SetPhotonDetPolish(G4double polish)
718 // Set the Polish of the PhotonDet, polish of 1 is a perfect mirror surface
719 // Pre: 0 < polish <= 1
720 {
721   fMPPCPolish = polish;
722   G4RunManager::GetRunManager()->GeometryHasBeenModified();
723 }
724 
725 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
726 
727 void WLSDetectorConstruction::SetPhotonDetReflectivity(G4double reflectivity)
728 // Set the Reflectivity of the PhotonDet, reflectivity of 1 is a perfect mirror
729 // Pre: 0 < reflectivity <= 1
730 {
731   fMPPCReflectivity = reflectivity;
732   G4RunManager::GetRunManager()->GeometryHasBeenModified();
733 }
734 
735 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
736 
737 void WLSDetectorConstruction::SetMirror(G4bool flag)
738 // Toggle to place the mirror or not at one end (-z end) of the fiber
739 // True means place the mirror, false means otherwise
740 {
741   fMirrorToggle = flag;
742   G4RunManager::GetRunManager()->GeometryHasBeenModified();
743 }
744 
745 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
746 
747 void WLSDetectorConstruction::SetXYRatio(G4double r)
748 // Set the ratio of the x and y radius of the ellipse (x/y)
749 // a ratio of 1 would produce a circle
750 {
751   fXYRatio = r;
752   G4RunManager::GetRunManager()->GeometryHasBeenModified();
753 }
754 
755 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
756 
757 void WLSDetectorConstruction::SetBarLength(G4double length)
758 // Set the length of the scintillator bar
759 {
760   fBarLength = length;
761   G4RunManager::GetRunManager()->GeometryHasBeenModified();
762 }
763 
764 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
765 
766 void WLSDetectorConstruction::SetBarBase(G4double side)
767 // Set the side of the scintillator bar
768 {
769   fBarBase = side;
770   G4RunManager::GetRunManager()->GeometryHasBeenModified();
771 }
772 
773 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
774 
775 void WLSDetectorConstruction::SetHoleRadius(G4double radius)
776 // Set the radius of the fiber hole
777 {
778   fHoleRadius = radius;
779   G4RunManager::GetRunManager()->GeometryHasBeenModified();
780 }
781 
782 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
783 
784 void WLSDetectorConstruction::SetCoatingThickness(G4double thick)
785 // Set thickness of the coating on the bars
786 {
787   fCoatingThickness = thick;
788   G4RunManager::GetRunManager()->GeometryHasBeenModified();
789 }
790 
791 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
792 
793 void WLSDetectorConstruction::SetCoatingRadius(G4double radius)
794 // Set inner radius of the corner bar coating
795 {
796   fCoatingRadius = radius;
797   G4RunManager::GetRunManager()->GeometryHasBeenModified();
798 }
799 
800 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
801 
802 G4double WLSDetectorConstruction::GetWLSFiberLength()
803 {
804   return fWLSfiberZ;
805 }
806 
807 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
808 
809 G4double WLSDetectorConstruction::GetBarLength()
810 {
811   return fBarLength;
812 }
813 
814 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
815 
816 G4double WLSDetectorConstruction::GetBarBase()
817 {
818   return fBarBase;
819 }
820 
821 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
822 
823 G4double WLSDetectorConstruction::GetHoleRadius()
824 {
825   return fHoleRadius;
826 }
827 
828 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
829 
830 G4double WLSDetectorConstruction::GetHoleLength()
831 {
832   return fHoleLength;
833 }
834 
835 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
836 
837 G4double WLSDetectorConstruction::GetFiberRadius()
838 {
839   return GetWLSFiberRMax();
840 }
841 
842 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
843 
844 G4double WLSDetectorConstruction::GetCoatingThickness()
845 {
846   return fCoatingThickness;
847 }
848 
849 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
850 
851 G4double WLSDetectorConstruction::GetCoatingRadius()
852 {
853   return fCoatingRadius;
854 }
855 
856 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
857 
858 G4double WLSDetectorConstruction::GetWLSFiberEnd()
859 {
860   return fWLSfiberOrigin + fWLSfiberZ;
861 }
862 
863 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
864 
865 G4double WLSDetectorConstruction::GetWLSFiberRMax()
866 {
867   if (fNumOfCladLayers == 2) return fClad2RY;
868   if (fNumOfCladLayers == 1) return fClad1RY;
869   return fWLSfiberRY;
870 }
871 
872 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
873 
874 G4double WLSDetectorConstruction::GetSurfaceRoughness()
875 {
876   return fSurfaceRoughness;
877 }
878 
879 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
880 
881 // Return True if the fiber construction is ideal
882 G4bool WLSDetectorConstruction::IsPerfectFiber()
883 {
884   return fSurfaceRoughness == 1. && fXYRatio == 1.
885          && (!fMirrorToggle || (fMirrorPolish == 1. && fMirrorReflectivity == 1.));
886 }
887 
888 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
889 
890 G4Material* WLSDetectorConstruction::FindMaterial(G4String name)
891 {
892   G4Material* material = G4Material::GetMaterial(name, true);
893   return material;
894 }
895