ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UltraDetectorConstruction.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file UltraDetectorConstruction.cc
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 // --------------------------------------------------------------
28 // GEANT 4 - ULTRA experiment example
29 // --------------------------------------------------------------
30 //
31 // Code developed by:
32 // B. Tome, M.C. Espirito-Santo, A. Trindade, P. Rodrigues
33 //
34 // ****************************************************
35 // * UltraDetectorConstruction.cc
36 // ****************************************************
37 //
38 // Class used in the definition of the Ultra setup consisting of:
39 // - the UVscope detector
40 // - an optional reflecting surface
41 // Optical photons can reach the UVscope either directly or after reflection in the
42 // surface, which can be polished or diffusing.
43 // The main part of the UVscope definition is the Fresnel lens construction based
44 // on the UltraFresnelLens class.
45 //
46 #include <cmath>
47 
50 #include "UltraPMTSD.hh"
51 #include "UltraFresnelLens.hh"
52 
53 #include "G4PhysicalConstants.hh"
54 #include "G4SystemOfUnits.hh"
55 #include "G4RunManager.hh"
56 #include "G4MTRunManager.hh"
57 #include "G4GeometryManager.hh"
58 #include "G4Material.hh"
59 #include "G4MaterialTable.hh"
60 #include "G4Element.hh"
61 #include "G4ElementTable.hh"
63 #include "G4Box.hh"
64 #include "G4Sphere.hh"
65 #include "G4Tubs.hh"
66 #include "G4LogicalVolume.hh"
67 #include "G4RotationMatrix.hh"
68 #include "G4ThreeVector.hh"
69 #include "G4Transform3D.hh"
70 #include "G4PVPlacement.hh"
71 #include "G4OpBoundaryProcess.hh"
72 #include "G4VisAttributes.hh"
73 #include "G4Colour.hh"
74 #include "G4Log.hh"
75 #include "G4SDManager.hh"
76 
77 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
78 
80  fReflectorOpticalSurface(0),
81  logicalPMT(0),
82  fReflectorLog(0),
83  fIsReflectorConstructed(false)
84 {
85  // Define wavelength limits for materials definition
86  lambda_min = 200*nm ;
87  lambda_max = 700*nm ;
88 
90 
92 }
93 
94 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
95 
97 {
98  delete fDetectorMessenger;
99 
101 }
102 
103 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
104 
106 {
107 // The experimental Hall
108 // ---------------------
109 
110  G4double World_x = 1.*m;
111  G4double World_y = 1.*m;
112  G4double World_z = 2*m;
113 
114  G4Box * World_box = new G4Box("World",World_x,World_y,World_z);
115 
116  // Get Air pointer from static funcion - (G4Material::GetMaterial)
117 
118  G4String name;
119  G4Material *Air = G4Material::GetMaterial(name = "Air");
120  G4LogicalVolume *World_log ;
121  World_log = new G4LogicalVolume(World_box,Air,"World",0,0,0);
122 
123  fWorld_phys = new G4PVPlacement(0,G4ThreeVector(),"World",World_log,0,false,0);
124 
125  G4VisAttributes* UniverseVisAtt = new G4VisAttributes(G4Colour(1.0,1.0,1.0));
126  UniverseVisAtt->SetVisibility(true);
127  UniverseVisAtt->SetForceWireframe(true);
128  World_log->SetVisAttributes(UniverseVisAtt);
130 
131 
132 
133  G4cout << "\n \n \n \n \n \n \n \n \n \n \n \n \n " << G4endl ;
134 
135  G4cout << "######################################################" << G4endl ;
136  G4cout << "# #" << G4endl ;
137  G4cout << "# #" << G4endl ;
138  G4cout << "# UltraDetectorConstruction: #" << G4endl ;
139  G4cout << "# #" << G4endl ;
140  G4cout << "# #" << G4endl ;
141 
143 
144 
145  G4cout << "# #" << G4endl ;
146  G4cout << "# #" << G4endl ;
147  G4cout << "######################################################" << G4endl ;
148 
149  fIsReflectorConstructed = false;
150 
151  return fWorld_phys;
152 }
153 
154 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
155 
157 {
158  UltraPMTSD* PMTSD = new UltraPMTSD("PMTSD");
161 }
162 
163 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
164 
166 {
167  G4double a, z, density;
168  G4String name, symbol;
169  G4int nel;
170 
171 
172 // ------------- Elements -------------
173  a = 1.01*g/mole;
174  G4Element* elH = new G4Element(name="Hydrogen", symbol="H", z=1., a);
175 
176  a = 12.01*g/mole;
177  G4Element* elC = new G4Element(name="Carbon", symbol="C", z=6., a);
178 
179  a = 14.01*g/mole;
180  G4Element* elN = new G4Element(name="Nitrogen", symbol="N", z=7., a);
181 
182  a = 16.00*g/mole;
183  G4Element* elO = new G4Element(name="Oxygen", symbol="O", z=8., a);
184 
185  a = 28.09*g/mole;
186  G4Element* elSi = new G4Element(name="Silicon", symbol="Si", z=14., a);
187 
188 
189 // ------------- Materials -------------
190 
191 
192 // Air
193 // ---
194  density = 1.29e-03*g/cm3;
195  G4Material* Air = new G4Material(name="Air", density, nel=2);
196  Air->AddElement(elN, .7);
197  Air->AddElement(elO, .3);
198 
199 
200 // Aluminum
201 // ---------
202  a = 26.98*g/mole;
203  density = 2.7*g/cm3;
204  new G4Material(name="Aluminum", z=13., a, density);
205 
206 
207 // Quartz
208 // -------
209 // density = 2.200*g/cm3; // fused quartz
210  density = 2.64*g/cm3; // crystalline quartz (c.f. PDG)
211  G4Material *Quartz = new G4Material(name="Quartz",density, nel=2);
212  Quartz->AddElement(elSi, 1) ;
213  Quartz->AddElement(elO , 2) ;
214 
215 
216 // PMMA C5H8O2 ( Acrylic )
217 // -------------
218  density = 1.19*g/cm3;
219  G4Material* Acrylic = new G4Material(name="Acrylic", density, nel=3);
220  Acrylic->AddElement(elC, 5);
221  Acrylic->AddElement(elH, 8);
222  Acrylic->AddElement(elO, 2);
223 
224 
226 // Construct Material Properties Tables
228 
229  const G4int NUMENTRIES = 2;
230 
231  // Energy bins
232  G4double X_RINDEX[NUMENTRIES] = {h_Planck*c_light/lambda_max, h_Planck*c_light/lambda_min} ;
233 
234 
235  // Air
236  G4double RINDEX_AIR[NUMENTRIES] = {1.00, 1.00} ;
237 
238 // Air refractive index at 20 oC and 1 atm (from PDG)
239  for(G4int j=0 ; j<NUMENTRIES ; j++){
240  RINDEX_AIR[j] = RINDEX_AIR[j] + 2.73*std::pow(10.0,-4) ;
241  }
242 
244  MPT_Air->AddProperty("RINDEX", X_RINDEX, RINDEX_AIR, NUMENTRIES);
245  Air->SetMaterialPropertiesTable(MPT_Air);
246 
248 // Photomultiplier (PMT) window
249 // The refractive index is for lime glass;
250 // wavelength dependence is not included and value at 400nm is used.
252 
253  // Refractive index
254 
255  const G4int N_RINDEX_QUARTZ = 2 ;
256  G4double X_RINDEX_QUARTZ[N_RINDEX_QUARTZ] = {h_Planck*c_light/lambda_max, h_Planck*c_light/lambda_min} ;
257  G4double RINDEX_QUARTZ[N_RINDEX_QUARTZ] = {1.54, 1.54};
258 
260  MPT_PMT->AddProperty("RINDEX", X_RINDEX_QUARTZ, RINDEX_QUARTZ, N_RINDEX_QUARTZ);
261 
262  Quartz->SetMaterialPropertiesTable(MPT_PMT);
263 
264 
266 // ACRYLIC Optical properties
268 
269 // Refractive index
270 
271  const G4int NENTRIES = 11 ;
272  G4double LAMBDA_ACRYLIC[NENTRIES] ;
273 
274 
275  G4double RINDEX_ACRYLIC[NENTRIES] ;
276  G4double ENERGY_ACRYLIC[NENTRIES] ;
277 
278 // Parameterization for refractive index of High Grade PMMA
279 
280  G4double bParam[4] = {1760.7010,-1.3687,2.4388e-3,-1.5178e-6} ;
281 
282  for(G4int i=0;i<NENTRIES; i++){
283 
284  LAMBDA_ACRYLIC[i] = lambda_min + i*(lambda_max-lambda_min)/float(NENTRIES-1) ;
285  RINDEX_ACRYLIC[i] = 0.0 ;
286 
287  for (G4int jj=0 ; jj<4 ; jj++)
288  {
289  RINDEX_ACRYLIC[i] += (bParam[jj]/1000.0)*std::pow(LAMBDA_ACRYLIC[i]/nm,jj) ;
290  }
291 
292  ENERGY_ACRYLIC[i] = h_Planck*c_light/LAMBDA_ACRYLIC[i] ; // Convert from wavelength to energy ;
293 // G4cout << ENERGY_ACRYLIC[i]/eV << " " << LAMBDA_ACRYLIC[i]/nm << " " << RINDEX_ACRYLIC[i] << G4endl ;
294 
295  }
296 
298  MPT_Acrylic->AddProperty("RINDEX", ENERGY_ACRYLIC, RINDEX_ACRYLIC, NENTRIES);
299 
300 
301 // Absorption
302  const G4int NENT = 25 ;
303  G4double LAMBDAABS[NENT] =
304  {
305  100.0,
306  246.528671, 260.605103, 263.853516, 266.019104, 268.726105,
307  271.433136, 273.598724, 276.305725, 279.554138, 300.127380,
308  320.159241, 340.191101, 360.764343, 381.337585, 399.745239,
309  421.401276, 440.891724, 460.382172, 480.414001, 500.987274,
310  520.477722, 540.509583, 559.458618,
311  700.0
312  } ;
313 
314  G4double ABS[NENT] = // Transmission (in %) of 3mm thick PMMA
315  {
316  0.0000000,
317  0.0000000, 5.295952, 9.657321, 19.937695, 29.283491,
318  39.252335, 48.598133, 58.255451, 65.109039, 79.439247,
319  85.669785, 89.719627, 91.277260, 91.588783, 91.900307,
320  91.588783, 91.277260, 91.277260, 91.588783, 91.588783,
321  91.900307, 91.900307, 91.588783,
322  91.5
323  } ;
324 
325 
326  MPT_Acrylic->AddProperty("ABSLENGTH", new G4MaterialPropertyVector()) ;
327  for(G4int i=0;i<NENT; i++){
328  G4double energy = h_Planck*c_light/(LAMBDAABS[i]*nm) ;
329  G4double abslength ;
330 
331  if (ABS[i] <= 0.0) {
332  abslength = 1.0/kInfinity ;
333  }
334  else {
335  abslength = -3.0*mm/(G4Log(ABS[i]/100.0)) ;
336  }
337 
338  MPT_Acrylic->AddEntry("ABSLENGTH", energy, abslength);
339 
340  }
341 
342  Acrylic->SetMaterialPropertiesTable(MPT_Acrylic);
343 
344 
346 
348 
349 }
350 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
351 
353 {
354  const G4double x = 40.0*cm;
355  const G4double y = 40.0*cm;
356  const G4double z = 1*cm;
357 
358  G4Box * box = new G4Box("Mirror",x,y,z);
359 
360  // Get Air pointer from static funcion - (G4Material::GetMaterial)
361 
362  G4String name;
363  G4Material *Al = G4Material::GetMaterial(name = "Aluminum");
364 
365  fReflectorLog = new G4LogicalVolume(box,Al,"Reflector",0,0,0);
366 
368 
369  // Rotate reflecting surface by 45. degrees around the OX axis.
370 
371  G4RotationMatrix *Surfrot = new G4RotationMatrix(G4ThreeVector(1.0,0.0,0.0),-pi/4.);
372 
373  new G4PVPlacement(Surfrot,SurfacePosition,"MirrorPV",fReflectorLog,fWorld_phys,false,0);
374 
375  G4VisAttributes* SurfaceVisAtt = new G4VisAttributes(G4Colour(0.0,0.0,1.0));
376  SurfaceVisAtt->SetVisibility(true);
377  SurfaceVisAtt->SetForceWireframe(true);
378  fReflectorLog->SetVisAttributes(SurfaceVisAtt);
379 
380  fReflectorOpticalSurface = new G4OpticalSurface("ReflectorOpticalSurface");
383 
384  const G4int NUM = 2;
386  G4double ICEREFLECTIVITY[NUM] = { 0.95, 0.95 };
387 
389  AirMirrorMPT->AddProperty("REFLECTIVITY", XX, ICEREFLECTIVITY,NUM);
391 
393 
394 #ifdef G4MULTITHREADED
396  //runManager->SetNumberOfThreads(2);
397 #else
399 #endif
400 
401  runManager->GeometryHasBeenModified();
402 
404 }
405 
406 
408 {
409  if (fReflectionType == "ground") {
410  G4cout << "Using ground reflecting surface " << G4endl ;
413  }
414  else {
415  G4cout << "Using mirror reflecting surface " << G4endl ;
418  }
419 }
420 
421 
422 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
423 
425 {
426 
427  // ------------- Volumes --------------
428 
430 
431  G4cout << "# #" << G4endl ;
432  G4cout << "# Building the Telescope ... #" << G4endl ;
433  G4cout << "# #" << G4endl ;
434 
436  // UVscope housing is a cylinder made of 1 mm thick aluminum
438 
439  G4double UVscopeHeight = 1030.0*mm ;
440  G4double UVscopeDiameter = 518.0*mm ;
441  G4double UVscopeThickness = 1.0*mm ;
442  G4double UVscopeBaffle = 514.0*mm ;
443 
444  G4double UVscopeInnerRadius = UVscopeDiameter/2.0-UVscopeThickness ;
445  G4double UVscopeOuterRadius = UVscopeDiameter/2.0 ;
446 
447  G4ThreeVector UVscopePosition = G4ThreeVector(0.0*m,0.0*m,-1.0*m) ;
448  G4String name;
449  G4Material* Al = G4Material::GetMaterial(name = "Aluminum");
450 
451 
452  G4Tubs *solidUVscope =
453  new G4Tubs("UVscopeSolid",UVscopeInnerRadius,UVscopeOuterRadius,UVscopeHeight/2.0,0.0,twopi) ;
454  G4LogicalVolume *logicUVscope =
455  new G4LogicalVolume(solidUVscope,Al,"UVscopeLV",0,0,0);
456  G4VPhysicalVolume *physicalUVscope =
457  new G4PVPlacement(0,UVscopePosition,"UVSCopePV",logicUVscope,fWorld_phys,false,0);
458 
459 
461  // Back cover of the UVscope cylinder
463 
464  G4Tubs *solidUVscopeBack =
465  new G4Tubs("UVscopeBackSolid",0.0,UVscopeOuterRadius,UVscopeThickness/2.0,0.0,twopi) ;
466 
467  G4LogicalVolume *logicUVscopeBack =
468  new G4LogicalVolume(solidUVscopeBack,Al,"UVscopeBackLV",0,0,0);
469 
470  G4ThreeVector UVscopeBackPosition ;
471  UVscopeBackPosition = UVscopePosition+G4ThreeVector(0.0*mm,0.0*mm,-(UVscopeHeight/2.0+UVscopeThickness/2.0)) ;
472  G4VPhysicalVolume *physicalUVscopeBack =
473  new G4PVPlacement(0,UVscopeBackPosition,"UVscopeBack",logicUVscopeBack,fWorld_phys,false,0);
474 
475 
476 
478 
479  G4cout << "# #" << G4endl ;
480  G4cout << "# Building the Fresnel lens ... #" << G4endl ;
481  G4cout << "# #" << G4endl ;
482 
483  G4double LensDiameter = 457*mm ; // Size of the optical active area of the lens.
484  G4int LensNumOfGrooves = 13 ;
485  //G4int LensNumOfGrooves = 129 ;
486  //G4int LensNumOfGrooves = 1287 ;
487 
488  G4double LensBorderThickness = 2.8*mm ; // Thickness of the border area.
489  G4double LensFocalLength = 441.973*mm ; // This parameter depends on the lens geometry, etc !!
490  G4Material *LensMaterial = G4Material::GetMaterial(name = "Acrylic") ;
491  G4ThreeVector LensPosition = UVscopePosition+G4ThreeVector(0.0*mm,0.0*mm,UVscopeHeight/2.0-UVscopeBaffle) ;
492 
493 
494  FresnelLens = new UltraFresnelLens(LensDiameter,LensNumOfGrooves,LensMaterial,fWorld_phys,LensPosition) ;
495 
496 
498  // Lens supporting ring (aluminum)
500 
501  G4Tubs *solidLensFrame = new G4Tubs("LensFrame",LensDiameter/2.0,UVscopeInnerRadius,LensBorderThickness/2.0,0.0,twopi) ;
502  G4LogicalVolume *logicLensFrame = new G4LogicalVolume(solidLensFrame,Al,"LensFrameLV",0,0,0);
503 
504  G4ThreeVector LensFramePosition ;
505  LensFramePosition = LensPosition+G4ThreeVector(0.0*mm,0.0*mm,-((FresnelLens->GetThickness())/2.0+solidLensFrame->GetZHalfLength())) ;
506 
507  G4VPhysicalVolume *physicalLensFrame =
508  new G4PVPlacement(0,LensFramePosition,"LensFramePV",logicLensFrame,fWorld_phys,false,0);
509 
511 
512 
513  G4cout << "# #" << G4endl ;
514  G4cout << "# Building the photomultiplier ... #" << G4endl ;
515  G4cout << "# #" << G4endl ;
516 
517 
518  // Photomultiplier window is a spherical section made of quartz
519 
520  G4double PMT_thick = 1.0*mm ; // Thickness of PMT window
521  G4double PMT_curv = 65.5*mm ; // Radius of curvature of PMT window
522  G4double StartTheta = (180.0-31.2)*pi/180. ;
523  G4double EndTheta = 31.2*pi/180. ;
524 
525  G4Sphere *solidPMT ;
526  solidPMT = new G4Sphere("PMT_solid",PMT_curv-PMT_thick,PMT_curv,0.0,twopi,StartTheta,EndTheta);
527 
528  G4Material* Quartz = G4Material::GetMaterial(name = "Quartz");
529  logicalPMT = new G4LogicalVolume(solidPMT,Quartz,"PMT_log",0,0,0);
530 
531 
532  // Place PMT is at Lens Focus
533 
534  G4ThreeVector PMTpos = LensPosition + G4ThreeVector(0.0*cm,0.0*cm,-(LensFocalLength+PMT_curv)) ;
535 
536  // Rotate PMT window through the axis OX by an angle = 180. degrees
537 
538  G4RotationMatrix *PMTrot = new G4RotationMatrix(G4ThreeVector(1.0,0.0,0.0),pi);
539  new G4PVPlacement(PMTrot,PMTpos,"PMT1",logicalPMT,fWorld_phys,false,0);
540 
541 
542  G4VisAttributes* PMTVisAtt = new G4VisAttributes(true,G4Colour(0.0,0.0,1.0)) ;
543  logicalPMT->SetVisAttributes(PMTVisAtt);
544 
546  // Optical properties of the interface between the Air and the walls of the
547  // UVscope cylinder (5% reflectivity)
548 
549 
550  G4cout << "# Defining interface's optical properties ... #" << G4endl ;
551  G4cout << "# #" << G4endl ;
552 
553 
554  G4OpticalSurface *OpticalAirPaint = new G4OpticalSurface("AirPaintSurface");
555  OpticalAirPaint->SetModel(unified);
556  OpticalAirPaint->SetType(dielectric_dielectric);
557  OpticalAirPaint->SetFinish(groundfrontpainted);
558 
559  const G4int NUM = 2;
561  G4double BLACKPAINTREFLECTIVITY[NUM] = { 0.05, 0.05 };
562  //G4double WHITEPAINTREFLECTIVITY[NUM] = { 0.99, 0.99 };
563 
565  AirPaintMPT->AddProperty("REFLECTIVITY", XX, BLACKPAINTREFLECTIVITY,NUM);
566  OpticalAirPaint->SetMaterialPropertiesTable(AirPaintMPT);
567 
568  //OpticalAirPaint->DumpInfo();
569 
570  new G4LogicalBorderSurface("Air/UVscope Cylinder Surface",fWorld_phys,physicalUVscope,OpticalAirPaint);
571 
572  new G4LogicalBorderSurface("Air/LensFrame Surface",fWorld_phys,physicalLensFrame,OpticalAirPaint);
573 
574  new G4LogicalBorderSurface("Air/UVscope Back Cover Surface",fWorld_phys,physicalUVscopeBack,OpticalAirPaint);
575 
576 
578 
579 
580  G4VisAttributes* LensVisAtt = new G4VisAttributes(G4Colour(1.0,0.0,0.0)) ; // Red
581  LensVisAtt ->SetVisibility(true);
582 
583 
584  if (FresnelLens){
586  }
587 
588  G4VisAttributes* UVscopeVisAtt = new G4VisAttributes(G4Colour(0.5,0.5,0.5)) ; // Gray
589  UVscopeVisAtt ->SetVisibility(true);
590 
591  physicalUVscope ->GetLogicalVolume()->SetVisAttributes(UVscopeVisAtt);
592  physicalUVscopeBack ->GetLogicalVolume()->SetVisAttributes(UVscopeVisAtt);
593  physicalLensFrame ->GetLogicalVolume()->SetVisAttributes(UVscopeVisAtt);
594 
596 
597  G4cout << "# #" << G4endl ;
598  G4cout << "# UVscope is built ! ... #" << G4endl ;
599  G4cout << "# #" << G4endl ;
600 
601 }
602 
603 
605 {
606 #ifdef G4MULTITHREADED
608  //runManager->SetNumberOfThreads(2);
609 #else
611 #endif
612 
613  fReflectionType = rtype;
614 
615  if (fReflectionType == "none") {
617  // Cleanup old geometry to delete reflecting surface
618  runManager->ReinitializeGeometry(true);
619  }
620  }
621  else {
624  }
626  }
627 }