28 #include "G4LogicalBorderSurface.hh"
29 #include "G4OpticalSurface.hh"
30 #include "G4LogicalVolume.hh"
31 #include "G4ThreeVector.hh"
32 #include "G4PVPlacement.hh"
34 #include "G4SystemOfUnits.hh"
35 #include "G4VisAttributes.hh"
38 #include "HCalDetectorConstruction.hh"
42 HCalDetectorConstruction* HCalDetectorConstruction::mInstance = 0;
44 HCalDetectorConstruction::HCalDetectorConstruction(): G4VUserDetectorConstruction()
46 fExpHall_x = fExpHall_y = fExpHall_z = 200.0*
cm;
53 HCalDetectorConstruction::~HCalDetectorConstruction(){;}
69 #ifdef _USE_ZEBRA_FILTER_
76 #define _HCAL_MASK_LINE_NUM_ (21+1)//(2*21+1)
78 static HcalMaskLine HcalMaskLines[_HCAL_MASK_LINE_NUM_] = {
87 { 10.90, 1.35, 247.5},
88 { 13.15, 1.35, 457.1},
89 { 15.40, 1.35, 247.5},
90 { 17.65, 1.35, 588.1},
91 { 19.90, 1.35, 247.5},
93 { 24.40, 1.35, 457.1},
94 { 26.65, 1.35, 326.1},
96 { 31.15, 1.00, 561.9},
97 { 33.05, 1.35, 326.1},
99 { 37.55, 1.35, 483.3},
100 { 39.80, 1.35, 378.5},
101 { 42.05, 1.35, 168.9},
102 { 44.30, 1.35, 588.1},
103 { 48.00, 0.25, 840.0}};
110 G4VPhysicalVolume *HCalDetectorConstruction::DefineHCalVolumes(
void )
115 G4Box* expHall_box =
new G4Box(
"World", fExpHall_x/2, fExpHall_y/2, fExpHall_z/2);
116 G4LogicalVolume* expHall_log =
new G4LogicalVolume(expHall_box, mQair,
"World", 0, 0, 0);
117 G4VPhysicalVolume* expHall_phys =
118 new G4PVPlacement(0, G4ThreeVector(), expHall_log,
"World", 0,
false, 0);
121 parser.
Read(
"block.gdml");
124 G4LogicalVolume *gdml = parser.
GetVolume(
"V-Product");
131 new G4PVPlacement(0, G4ThreeVector(1.01*
cm, 1.01*
cm, 0), gdml,
"V-Product", expHall_log,
false, 0);
140 double TowerWidth = 100.0*
mm;
141 double TowerHeight = 100.0*
mm;
147 double SubCellLength = 23.4*
mm;
149 const unsigned SubCellNum = 37;
152 double TowerLength = SubCellNum * SubCellLength + 10.0*
mm;
155 double TowerEnvelopeWidth = TowerWidth - 2*
SmallGap;
156 double TowerEnvelopeHeight = TowerHeight - 2*SmallGap - mGeometry->mSteelSpacerThickness;
157 double TowerEnvelopeLength = TowerLength - 2*
SmallGap;
159 double SubCellWidth = 96.0*
mm;
160 double SubCellHeight = TowerEnvelopeHeight - 2*
SmallGap;
162 double SubCellEnvelopeWidth = SubCellWidth - 2*
SmallGap;
163 double SubCellEnvelopeHeight = SubCellHeight - 2*
SmallGap;
164 double SubCellEnvelopeLength = SubCellLength - 2*
SmallGap;
166 double AbsorberPlateWidth = SubCellWidth - 2*
SmallGap;
167 double AbsorberPlateHeight = SubCellHeight - 2*
SmallGap;
170 double AbsorberPlateThickness = 20.0*
mm;
176 double ScintillatorPlateThickness = 3.0*
mm;
180 double ScintillatorPlateWidth = 95.0*
mm;
181 double ScintillatorPlateHeight = 97.0*
mm;
182 double ScPlateAirAppendixLength = 0.3*
mm;
185 double WlsPlateThickness = 3.0*
mm;
186 double WlsPlateLength = SubCellNum * SubCellLength;
187 double WlsPlateHeight = 97.0*
mm;
189 double WlsPlateAirAppendixLength = 1.0*
mm;
194 double MetallizedMylarThickness = 0.05*
mm;
195 #ifdef _USE_ZEBRA_FILTER_
196 double ZebraFilterThickness = 0.05*
mm;
199 double OpticalGlueThickness = _HCAL_OPTICAL_GLUE_THICKNESS_;
205 printf(
"\n\nIR box size: Z +/- %.2f [cm], R ~ %.2f [cm]\n\n",
206 eic->GetIrRegionLength()/2,
eic->GetIrRegionRadius());
209 auto expHall_phys =
eic->ConstructG4World();
210 expHall_phys->GetLogicalVolume()->SetVisAttributes(G4VisAttributes::Invisible);
216 dynamic_cast<EicToyModel *
>(fin.Get(
"EicToyModel"));
219 eic->PlaceG4Volumes(expHall_phys);
222 new G4PVPlacement(0, G4ThreeVector(0, 0, zOffset), myhcal_log,
"MyHCal", expHall_log,
false, 0);
223 auto hcal_bubble_log =
eic->fwd()->get(
"HCal")->GetG4Volume()->GetLogicalVolume();
224 new G4PVPlacement(0, G4ThreeVector(0, 0, 0), myhcal_log,
"MyHCal", hcal_bubble_log,
false, 0);
229 auto expHall_log =
eic->bck()->get(
"HCal")->GetG4Volume()->GetLogicalVolume();
236 expHall_phys->GetLogicalVolume()->SetVisAttributes(G4VisAttributes::Invisible);
241 if (mGeometry->mUseFrontSteelPlate) {
242 G4Box *front_plate_box =
243 new G4Box(
"FrontPlate", (mGeometry->mXdim*TowerWidth)/2, (mGeometry->mYdim*TowerHeight)/2,
244 mGeometry->mFrontSteelPlateThickness/2);
245 G4LogicalVolume *front_plate_log =
new G4LogicalVolume(front_plate_box, mSteel,
"FrontPlate", 0, 0, 0);
247 double zOffset = -(TowerLength + mGeometry->mFrontSteelPlateThickness)/2;
249 new G4PVPlacement(0, G4ThreeVector(0, 0, zOffset),
250 front_plate_log,
"FrontPlate", expHall_log,
false, 0);
255 G4Box *tower_box =
new G4Box(
"Tower", TowerWidth/2, TowerHeight/2, TowerLength/2);
258 G4LogicalVolume *tower_log =
new G4LogicalVolume(tower_box, mQair,
"Tower", 0, 0, 0);
259 for(
unsigned ix=0; ix<mGeometry->mXdim; ix++)
260 for(
unsigned iy=0; iy<mGeometry->mYdim; iy++) {
261 double xOffset = (ix-(mGeometry->mXdim-1)/2.0)*TowerWidth;
262 double yOffset = (iy-(mGeometry->mYdim-1)/2.0)*TowerHeight;
266 new G4PVPlacement(0, G4ThreeVector(xOffset + 50*
cm, yOffset - 0*
cm, 0),
267 tower_log,
"Tower", expHall_log,
false, ix*mGeometry->mYdim + iy);
272 G4Box *tower_envelope_box =
273 new G4Box(
"TowerEnvelope", TowerEnvelopeWidth/2, TowerEnvelopeHeight/2, TowerEnvelopeLength/2);
274 G4LogicalVolume *tower_envelope_log =
275 new G4LogicalVolume(tower_envelope_box, mAir,
"TowerEnvelope", 0, 0, 0);
276 #ifdef _HCAL_USE_MYLAR_REFLECTOR_
277 G4VPhysicalVolume *tower_envelope_phys = 0;
280 double yOffset = -TowerHeight/2 + SmallGap + TowerEnvelopeHeight/2;
281 #ifdef _HCAL_USE_MYLAR_REFLECTOR_
282 tower_envelope_phys =
284 new G4PVPlacement(0, G4ThreeVector(0, yOffset, 0), tower_envelope_log,
"TowerEnvelope", tower_log,
false, 0);
289 G4Box *subcell_box =
new G4Box(
"SubCell", SubCellWidth/2, SubCellHeight/2, SubCellLength/2);
290 G4LogicalVolume *subcell_log =
new G4LogicalVolume(subcell_box, mAir,
"SubCell", 0, 0, 0);
293 double xOffset = -TowerEnvelopeWidth/2 + SmallGap + SubCellWidth/2;
295 for(
unsigned iq=0; iq<SubCellNum; iq++) {
296 double zOffset = (iq-(SubCellNum-1)/2.0)*SubCellLength;
300 new G4PVPlacement(0, G4ThreeVector(xOffset, 0, zOffset), subcell_log,
301 "SubCell", tower_envelope_log,
false, iq);
308 G4Box *subcell_envelope_box =
309 new G4Box(
"SubCellEnvelope", SubCellEnvelopeWidth/2, SubCellEnvelopeHeight/2, SubCellEnvelopeLength/2);
310 G4LogicalVolume *subcell_envelope_log =
311 new G4LogicalVolume(subcell_envelope_box, mAir,
"SubCellEnvelope", 0, 0, 0);
312 G4VPhysicalVolume *subcell_envelope_phys =
313 new G4PVPlacement(0, G4ThreeVector(), subcell_envelope_log,
"SubCellEnvelope", subcell_log,
false, 0);
317 G4Box *scintPlate_box =
new G4Box(
"ScintPlate", ScintillatorPlateWidth/2, ScintillatorPlateHeight/2,
318 ScintillatorPlateThickness/2);
319 G4LogicalVolume *scintPlate_log =
new G4LogicalVolume(scintPlate_box, mEJ212,
"ScintPlate", 0, 0, 0);
322 double xOffset = -SubCellEnvelopeWidth /2 + SmallGap + ScintillatorPlateWidth /2 + ScPlateAirAppendixLength;
323 double yOffset = -SubCellEnvelopeHeight/2 + SmallGap + ScintillatorPlateHeight /2;
324 double zOffset = -SubCellEnvelopeLength/2 + SmallGap + ScintillatorPlateThickness/2;
326 G4VPhysicalVolume *sc_phys =
327 new G4PVPlacement(0, G4ThreeVector(xOffset, yOffset, zOffset), scintPlate_log,
"ScintPlate",
328 subcell_envelope_log,
false, 0);
333 double xxOffset = -SubCellEnvelopeWidth /2 + SmallGap + ScPlateAirAppendixLength/2;
335 G4Box *xx_box =
new G4Box(
"XxPlate", ScPlateAirAppendixLength/2, ScintillatorPlateHeight/2,
336 ScintillatorPlateThickness/2);
337 G4LogicalVolume *xx_log =
new G4LogicalVolume(xx_box, mAir,
"XxPlate", 0, 0, 0);
338 G4PVPlacement *xx_phys =
339 new G4PVPlacement(0, G4ThreeVector(xxOffset, yOffset, zOffset),
340 xx_log,
"XxPlate", subcell_envelope_log,
false, 0);
344 G4OpticalSurface* opScPaintSurface =
345 CreateLambertianSurface(
"ScPaintSurface", _BC620_PAINT_REFLECTIVITY_);
346 new G4LogicalBorderSurface(
"ScPaintAirSurface", sc_phys, xx_phys, opScPaintSurface);
347 new G4LogicalBorderSurface(
"AirPaintScSurface", xx_phys, sc_phys, opScPaintSurface);
352 if (_EJ212_SCINTILLATOR_SURFACE_REFLECTIVITY_ != 1.00 || _EJ212_SCINTILLATOR_SURFACE_ROUGHNESS_)
353 DefineSkinSurface(
"ScintSurface", scintPlate_log, _EJ212_SCINTILLATOR_SURFACE_REFLECTIVITY_,
354 _EJ212_SCINTILLATOR_SURFACE_ROUGHNESS_);
359 G4Box* absorber_box =
360 new G4Box(
"Absorber", AbsorberPlateWidth/2, AbsorberPlateHeight/2, AbsorberPlateThickness/2);
361 #ifdef _USE_STEEL_ABSORBER_
362 G4LogicalVolume* absorber_log =
new G4LogicalVolume(absorber_box, mSteel,
"Absorber", 0, 0, 0);
364 G4LogicalVolume* absorber_log =
new G4LogicalVolume(absorber_box, mAbsorber,
"Absorber", 0, 0, 0);
368 double zOffset = SubCellEnvelopeLength/2 - SmallGap - AbsorberPlateThickness/2;
370 G4VPhysicalVolume* absorber_phys =
371 new G4PVPlacement(0, G4ThreeVector(0, 0, zOffset), absorber_log,
"Absorber",
372 subcell_envelope_log,
false, 0);
378 G4OpticalSurface* opAbsorberSurface =
379 CreateLambertianSurface(
"AbsorberSurface", _ABSORBER_PAINT_REFLECTIVITY_);
380 new G4LogicalBorderSurface(
"AbsorberSurface", subcell_envelope_phys, absorber_phys, opAbsorberSurface);
386 double wlsXoffset = TowerEnvelopeWidth/2 - WlsPlateThickness/2 -
SmallGap;
387 double wlsYoffset = -TowerEnvelopeHeight/2 + SmallGap + WlsPlateHeight/2;
389 G4Box *wls_box =
new G4Box(
"WlsPlate", WlsPlateThickness/2, WlsPlateHeight/2, WlsPlateLength/2);
390 G4LogicalVolume *wls_log =
new G4LogicalVolume(wls_box, mEJ280,
"WlsPlate", 0, 0, 0);
392 G4VPhysicalVolume *wls_phys =
393 new G4PVPlacement(0, G4ThreeVector(wlsXoffset, wlsYoffset, 0), wls_log,
"WlsPlate", tower_envelope_log,
false, 0);
396 if (_WLS_SURFACE_REFLECTIVITY_ != 1.00 || _WLS_SURFACE_ROUGHNESS_)
397 DefineSkinSurface(
"WlsSurface", wls_log, _WLS_SURFACE_REFLECTIVITY_,
398 _WLS_SURFACE_ROUGHNESS_);
402 G4Box *qq_box =
new G4Box(
"QqPlate", WlsPlateThickness/2, WlsPlateHeight/2, WlsPlateAirAppendixLength/2);
403 G4LogicalVolume *qq_log =
new G4LogicalVolume(qq_box, mAir,
"QqPlate", 0, 0, 0);
404 G4PVPlacement *qq_phys =
405 new G4PVPlacement(0, G4ThreeVector(wlsXoffset, wlsYoffset, -(WlsPlateLength+WlsPlateAirAppendixLength)/2),
406 qq_log,
"QqPlate", tower_envelope_log,
false, 0);
410 G4OpticalSurface* opWlsPaintSurface =
411 CreateLambertianSurface(
"WlsPaintSurface", _BC620_PAINT_REFLECTIVITY_);
412 new G4LogicalBorderSurface(
"WlsPaintAirSurface", wls_phys, qq_phys, opWlsPaintSurface);
413 new G4LogicalBorderSurface(
"AirPaintWlsSurface", qq_phys, wls_phys, opWlsPaintSurface);
418 #ifdef _HCAL_USE_MYLAR_REFLECTOR_
420 G4Box *mylar_box =
new G4Box(
"Mylar", MetallizedMylarThickness/2, WlsPlateHeight/2, WlsPlateLength/2);
422 G4LogicalVolume *mylar_log =
new G4LogicalVolume(mylar_box, mMylar,
"Mylar", 0, 0, 0);
424 double xOffset = (TowerEnvelopeWidth - MetallizedMylarThickness)/2 - SmallGap;
425 G4PVPlacement *mylar_phys =
426 new G4PVPlacement(0, G4ThreeVector(xOffset, wlsYoffset, 0), mylar_log,
"Mylar", tower_envelope_log,
false, 0);
430 G4OpticalSurface* opMylarSurface =
new G4OpticalSurface(
"MylarSurface");
431 opMylarSurface->SetType(dielectric_metal);
433 opMylarSurface->SetFinish(polished);
434 opMylarSurface->SetModel(unified);
436 G4double reflectivity[_GDIM_];
437 for(
int iq=0; iq<_GDIM_; iq++)
438 reflectivity[iq] = _HCAL_MYLAR_REFLECTIVITY_;
439 G4MaterialPropertiesTable *mylarST =
new G4MaterialPropertiesTable();
440 mylarST->AddProperty(
"REFLECTIVITY",
gPhotonEnergy, reflectivity, _GDIM_);
441 opMylarSurface->SetMaterialPropertiesTable(mylarST);
443 new G4LogicalBorderSurface(
"MylarSurface", tower_envelope_phys, mylar_phys, opMylarSurface);
448 #ifdef _USE_ZEBRA_FILTER_
450 double xOffset = wlsXoffset - WlsPlateThickness/2 - SmallGap - ZebraFilterThickness/2;
453 for(
unsigned iq=0; iq<_HCAL_MASK_LINE_NUM_; iq++) {
454 HcalMaskLine *line = HcalMaskLines + iq;
457 snprintf(name, 1024-1,
"ZebraLine%2d", iq);
459 G4Box *black_box =
new G4Box(name, ZebraFilterThickness/2*
mm, line->width/2*
mm, line->length/2*
mm);
460 G4LogicalVolume *black_log =
new G4LogicalVolume(black_box, mMylar, name, 0, 0, 0);
462 double zOffset = (WlsPlateLength - line->length*
mm)/2;
464 for(
unsigned tb=0; tb<2; tb++) {
465 double yOffset = wlsYoffset + (tb ? -1.0 : 1.0)*line->y0*
mm;
468 if (!iq && tb)
continue;
471 new G4PVPlacement(0, G4ThreeVector(xOffset, yOffset, zOffset), black_log, name, tower_envelope_log,
false, tb);
480 G4LogicalVolume *sipm_log =
new G4LogicalVolume(sipm_box, mSilicon,
"SiPM", 0, 0, 0);
481 G4VisAttributes *sipmVisAtt =
new G4VisAttributes(G4Colour(0.,1.,1.));
482 sipm_log->SetVisAttributes(sipmVisAtt);
487 new G4PVPlacement(0, G4ThreeVector(wlsXoffset, wlsYoffset, zOffsetSiPM), sipm_log,
488 "SiPM", tower_envelope_log,
false, 0);
492 G4LogicalVolume *sensor_log =
new G4LogicalVolume(sensor_box, mQair,
"Sensor", 0, 0, 0);
493 new G4PVPlacement(0, G4ThreeVector(), sensor_log,
"Sensor", sipm_log,
false, 0);
499 G4Box *opt_glue_box =
new G4Box(
"OptGlue",
SiPMSize/2,
SiPMSize/2, OpticalGlueThickness/2);
500 G4LogicalVolume *opt_glue_log =
new G4LogicalVolume(opt_glue_box, mRTV3145,
"OptGlue", 0, 0, 0);
503 G4LogicalVolume *sipm_log =
new G4LogicalVolume(sipm_box, mSilicon,
"SiPM", 0, 0, 0);
504 G4VisAttributes *sipmVisAtt =
new G4VisAttributes(G4Colour(0.,1.,1.));
505 sipm_log->SetVisAttributes(sipmVisAtt);
508 double zOffsetGlue = (WlsPlateLength + OpticalGlueThickness)/2;
509 double zOffsetSiPM = WlsPlateLength/2 + OpticalGlueThickness +
SiPMThickness/2;
511 #ifdef _USE_31_SIPM_PER_TOWER_
512 for(
unsigned iq=0; iq<31; iq++) {
515 double yOffset = (iq-15.0)*3.02*
mm;
518 new G4PVPlacement(0, G4ThreeVector(wlsXoffset, yOffset, zOffsetGlue), opt_glue_log,
519 "OptGlue", tower_envelope_log,
false, iq);
522 new G4PVPlacement(0, G4ThreeVector(wlsXoffset, yOffset, zOffsetSiPM), sipm_log,
523 "SiPM", tower_envelope_log,
false, iq);
527 for(
unsigned tb=0; tb<2; tb++)
528 for(
unsigned iq=0; iq<4; iq++) {
530 double yOffset = (tb ? -1.0 : 1.0)*(iq+1)*10.0*
mm;
533 new G4PVPlacement(0, G4ThreeVector(wlsXoffset, yOffset, zOffsetGlue), opt_glue_log,
534 "OptGlue", tower_envelope_log,
false, tb*4+iq);
537 new G4PVPlacement(0, G4ThreeVector(wlsXoffset, yOffset, zOffsetSiPM), sipm_log,
538 "SiPM", tower_envelope_log,
false, tb*4+iq);
545 G4LogicalVolume *sensor_log =
new G4LogicalVolume(sensor_box, mQair,
"Sensor", 0, 0, 0);
546 new G4PVPlacement(0, G4ThreeVector(), sensor_log,
"Sensor", sipm_log,
false, 0);
551 if (mGeometry->mUseSteelSpacers) {
552 G4Box *spacer_box =
new G4Box(
"Spacer", TowerWidth/2, mGeometry->mSteelSpacerThickness/2, TowerLength/2);
553 G4LogicalVolume *spacer_log =
new G4LogicalVolume(spacer_box, mSteel,
"Spacer", 0, 0, 0);
555 double yOffset = TowerHeight/2 - mGeometry->mSteelSpacerThickness/2;
557 new G4PVPlacement(0, G4ThreeVector(0, yOffset, 0),
558 spacer_log,
"Spacer", tower_log,
false, 0);
568 G4VPhysicalVolume* HCalDetectorConstruction::Construct()
571 for(
int iq=0; iq<_GDIM_; iq++)
581 return DefineHCalVolumes();