5 #include <phparameter/PHParameters.h>
16 #include <Geant4/G4Box.hh>
17 #include <Geant4/G4Cons.hh>
18 #include <Geant4/G4LogicalSkinSurface.hh>
19 #include <Geant4/G4LogicalVolume.hh>
20 #include <Geant4/G4Material.hh>
21 #include <Geant4/G4MaterialPropertiesTable.hh>
22 #include <Geant4/G4OpticalSurface.hh>
23 #include <Geant4/G4PVPlacement.hh>
24 #include <Geant4/G4PVReplica.hh>
25 #include <Geant4/G4PhysicalConstants.hh>
26 #include <Geant4/G4Polyhedra.hh>
27 #include <Geant4/G4RotationMatrix.hh>
28 #include <Geant4/G4String.hh>
29 #include <Geant4/G4SubtractionSolid.hh>
30 #include <Geant4/G4SystemOfUnits.hh>
31 #include <Geant4/G4ThreeVector.hh>
32 #include <Geant4/G4Transform3D.hh>
33 #include <Geant4/G4Tubs.hh>
34 #include <Geant4/G4Types.hh>
35 #include <Geant4/G4VPhysicalVolume.hh>
53 , m_Params(parameters)
55 , m_ActiveFlag(m_Params->get_int_param(
"active"))
56 , m_AbsorberActiveFlag(m_Params->get_int_param(
"absorberactive"))
57 , m_doLightProp(
false)
59 for (
int i = 0; i < 3; i++)
65 for (
int i = 3; i < 7; i++)
84 G4LogicalVolume* mylogvol = volume->GetLogicalVolume();
107 std::cout <<
"PHG4ForwardEcalDetector: Begin Construction" << std::endl;
119 G4VSolid* beampipe_cutout =
new G4Cons(
"FEMC_beampipe_cutout",
122 (
m_dZ + tower_readout_dz),
124 G4VSolid* ecal_envelope_solid =
new G4Cons(
"FEMC_envelope_solid_cutout",
127 (
m_dZ + tower_readout_dz) / 2.0,
131 G4LogicalVolume* ecal_envelope_log =
new G4LogicalVolume(ecal_envelope_solid, WorldMaterial,
"hFEMC_envelope", 0, 0, 0);
137 G4RotationMatrix ecal_rotm;
138 ecal_rotm.rotateX(
m_XRot);
139 ecal_rotm.rotateY(
m_YRot);
140 ecal_rotm.rotateZ(
m_ZRot);
146 ecal_envelope_log, name_envelope, logicWorld, 0,
false,
OverlapCheck());
149 G4LogicalVolume* singletower[7] = {
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr};
150 typedef std::map<std::string, towerposition>::iterator it_type;
153 for (
int i = 0; i < 7; i++)
155 if (iterator->second.type == i && singletower[i] ==
nullptr)
164 std::cout << singletower << std::endl;
178 std::cout <<
"PHG4ForwardEcalDetector: Build logical volume for single tower, type = " << type << std::endl;
187 G4double thickness_layer =
m_TowerDz[2] / (float) nlayers;
189 G4double thickness_cell = 5.6 *
mm;
190 G4double thickness_absorber = 1.55 *
mm;
191 G4double thickness_scintillator = 4.0 *
mm;
198 G4double fiber_extra_length = 0.0;
200 if (fiber_diam > 0) fiber_extra_length = 0.5 *
cm;
206 G4VSolid* single_tower_solid =
new G4Box(
"single_tower_solid2",
209 (
m_TowerDz[2] + tower_readout_dz) / 2.0);
210 G4VSolid* single_tower_solid_replica =
new G4Box(
"single_tower_solid_replica",
215 G4LogicalVolume* single_tower_logic =
new G4LogicalVolume(single_tower_solid,
217 "single_tower_logic2",
224 std::cout <<
" m_TowerDz[2] = " <<
m_TowerDz[2] <<
" thickness_layer = " << thickness_layer <<
" thickness_cell = " << thickness_cell << std::endl;
227 if (thickness_layer <= thickness_cell)
229 std::cout << __PRETTY_FUNCTION__
230 <<
"Tower size z (m_TowerDz[2) from database is too thin. "
231 <<
"It does not fit the layer structure as described in https://doi.org/10.1016/S0168-9002(02)01954-X !" << std::endl
232 <<
"Abort" << std::endl;
233 std::cout <<
" m_TowerDz[2] = " <<
m_TowerDz[2] <<
" i.e. nlayers " << nlayers <<
" * thickness_layer " << thickness_layer <<
" <= thickness_cell " << thickness_cell << std::endl;
240 G4VSolid* miniblock_solid =
new G4Box(
"miniblock_solid",
243 thickness_cell / 2.0);
244 G4LogicalVolume* miniblock_logic =
new G4LogicalVolume(miniblock_solid,
252 G4VSolid* solid_absorber =
new G4Box(
"single_plate_absorber_solid2",
255 thickness_absorber / 2.0);
257 G4VSolid* solid_scintillator =
new G4Box(
"single_plate_scintillator2",
262 thickness_scintillator / 2.0);
264 if (clamp_plate_width > 0)
266 G4VSolid* solid_clamp1 =
new G4Box(
"single_plate_clamp_solid1",
269 clamp_plate_width / 2.0);
270 G4LogicalVolume* logic_clampplate =
new G4LogicalVolume(solid_clamp1,
278 new G4PVPlacement(0, G4ThreeVector(0, 0, (
m_dZ + tower_readout_dz) / 2.0 - clamp_plate_width / 2.0),
284 if (nFibers > 0 && nFibers == 5 && fiber_diam > 0)
286 G4VSolid* cutoutfiber_solid =
new G4Tubs(
"cutoutfiber_solid",
289 single_tower_solid_replica =
new G4SubtractionSolid(G4String(
"single_tower_solid_replica_cu1"), single_tower_solid_replica, cutoutfiber_solid, 0, G4ThreeVector(0, 0, 0.));
290 single_tower_solid_replica =
new G4SubtractionSolid(G4String(
"single_tower_solid_replica_cu2"), single_tower_solid_replica, cutoutfiber_solid, 0, G4ThreeVector(-
m_TowerDx[2] / 4.0,
m_TowerDy[2] / 4.0, 0.));
291 single_tower_solid_replica =
new G4SubtractionSolid(G4String(
"single_tower_solid_replica_cu3"), single_tower_solid_replica, cutoutfiber_solid, 0, G4ThreeVector(
m_TowerDx[2] / 4.0,
m_TowerDy[2] / 4.0, 0.));
292 single_tower_solid_replica =
new G4SubtractionSolid(G4String(
"single_tower_solid_replica_cu4"), single_tower_solid_replica, cutoutfiber_solid, 0, G4ThreeVector(
m_TowerDx[2] / 4.0, -
m_TowerDy[2] / 4.0, 0.));
293 single_tower_solid_replica =
new G4SubtractionSolid(G4String(
"single_tower_solid_replica_cu5"), single_tower_solid_replica, cutoutfiber_solid, 0, G4ThreeVector(-
m_TowerDx[2] / 4.0, -
m_TowerDy[2] / 4.0, 0.));
295 solid_absorber =
new G4SubtractionSolid(G4String(
"solid_absorber_cu1"), solid_absorber, cutoutfiber_solid, 0, G4ThreeVector(0, 0, 0.));
296 solid_absorber =
new G4SubtractionSolid(G4String(
"solid_absorber_cu2"), solid_absorber, cutoutfiber_solid, 0, G4ThreeVector(-
m_TowerDx[2] / 4.0,
m_TowerDy[2] / 4.0, 0.));
297 solid_absorber =
new G4SubtractionSolid(G4String(
"solid_absorber_cu3"), solid_absorber, cutoutfiber_solid, 0, G4ThreeVector(
m_TowerDx[2] / 4.0,
m_TowerDy[2] / 4.0, 0.));
298 solid_absorber =
new G4SubtractionSolid(G4String(
"solid_absorber_cu4"), solid_absorber, cutoutfiber_solid, 0, G4ThreeVector(
m_TowerDx[2] / 4.0, -
m_TowerDy[2] / 4.0, 0.));
299 solid_absorber =
new G4SubtractionSolid(G4String(
"solid_absorber_cu5"), solid_absorber, cutoutfiber_solid, 0, G4ThreeVector(-
m_TowerDx[2] / 4.0, -
m_TowerDy[2] / 4.0, 0.));
301 solid_scintillator =
new G4SubtractionSolid(G4String(
"solid_scintillator_cu1"), solid_scintillator, cutoutfiber_solid, 0, G4ThreeVector(0, 0, 0.));
302 solid_scintillator =
new G4SubtractionSolid(G4String(
"solid_scintillator_cu2"), solid_scintillator, cutoutfiber_solid, 0, G4ThreeVector(-
m_TowerDx[2] / 4.0,
m_TowerDy[2] / 4.0, 0.));
303 solid_scintillator =
new G4SubtractionSolid(G4String(
"solid_scintillator_cu3"), solid_scintillator, cutoutfiber_solid, 0, G4ThreeVector(
m_TowerDx[2] / 4.0,
m_TowerDy[2] / 4.0, 0.));
304 solid_scintillator =
new G4SubtractionSolid(G4String(
"solid_scintillator_cu4"), solid_scintillator, cutoutfiber_solid, 0, G4ThreeVector(
m_TowerDx[2] / 4.0, -
m_TowerDy[2] / 4.0, 0.));
305 solid_scintillator =
new G4SubtractionSolid(G4String(
"solid_scintillator_cu5"), solid_scintillator, cutoutfiber_solid, 0, G4ThreeVector(-
m_TowerDx[2] / 4.0, -
m_TowerDy[2] / 4.0, 0.));
307 if (clamp_plate_width > 0)
309 G4VSolid* solid_clamp2 =
new G4Box(
"single_plate_clamp_solid2",
312 clamp_plate_width / 2.0);
313 solid_clamp2 =
new G4SubtractionSolid(G4String(
"solid_clamp2_cu1"), solid_clamp2, cutoutfiber_solid, 0, G4ThreeVector(0, 0, 0.));
314 solid_clamp2 =
new G4SubtractionSolid(G4String(
"solid_clamp2_cu2"), solid_clamp2, cutoutfiber_solid, 0, G4ThreeVector(-
m_TowerDx[2] / 4.0,
m_TowerDy[2] / 4.0, 0.));
315 solid_clamp2 =
new G4SubtractionSolid(G4String(
"solid_clamp2_cu3"), solid_clamp2, cutoutfiber_solid, 0, G4ThreeVector(
m_TowerDx[2] / 4.0,
m_TowerDy[2] / 4.0, 0.));
316 solid_clamp2 =
new G4SubtractionSolid(G4String(
"solid_clamp2_cu4"), solid_clamp2, cutoutfiber_solid, 0, G4ThreeVector(
m_TowerDx[2] / 4.0, -
m_TowerDy[2] / 4.0, 0.));
317 solid_clamp2 =
new G4SubtractionSolid(G4String(
"solid_clamp2_cu5"), solid_clamp2, cutoutfiber_solid, 0, G4ThreeVector(-
m_TowerDx[2] / 4.0, -
m_TowerDy[2] / 4.0, 0.));
318 G4LogicalVolume* logic_clampplate2 =
new G4LogicalVolume(solid_clamp2,
326 new G4PVPlacement(0, G4ThreeVector(0, 0, (tower_readout_dz) / 2.0 - clamp_plate_width -
m_TowerDz[2] / 2.0 - clamp_plate_width / 2.0),
334 if (width_coating > 0)
336 G4double depthCoating = 0.93 * thickness_scintillator;
337 G4double zPlaneCoating[2] = {0, depthCoating};
338 G4double rInnerCoating[2] = {(
m_TowerDx[2] - 2 * width_coating) / 2, (
m_TowerDx[2] - 2 * width_coating) / 2.0};
340 G4VSolid* solid_coating =
new G4Polyhedra(
"solid_coating",
343 zPlaneCoating, rInnerCoating, rOuterCoating);
344 G4LogicalVolume* logic_coating =
new G4LogicalVolume(solid_coating,
352 G4RotationMatrix* rotCoating =
new G4RotationMatrix();
353 rotCoating->rotateZ(
M_PI / 4);
354 new G4PVPlacement(rotCoating, G4ThreeVector(0, 0, thickness_cell / 2.0 - depthCoating),
359 solid_scintillator =
new G4SubtractionSolid(G4String(
"solid_scintillator_cuCoating"), solid_scintillator, solid_coating, rotCoating, G4ThreeVector(0, 0, thickness_scintillator / 2.0 - depthCoating));
361 G4LogicalVolume* logic_absorber =
new G4LogicalVolume(solid_absorber,
363 "single_plate_absorber_logic2",
366 G4LogicalVolume* logic_scint =
new G4LogicalVolume(solid_scintillator,
367 material_scintillator,
368 "hEcal_scintillator_plate_logic2",
382 new G4PVPlacement(0, G4ThreeVector(0, 0, -thickness_cell / 2.0 + thickness_absorber / 2.0),
388 new G4PVPlacement(0, G4ThreeVector(0, 0, thickness_cell / 2.0 - thickness_scintillator / 2.0),
394 G4LogicalVolume* single_tower_replica_logic =
new G4LogicalVolume(single_tower_solid_replica,
396 "single_tower_replica_logic",
400 new G4PVReplica(name_tower, miniblock_logic, single_tower_replica_logic,
401 kZAxis, nlayers, thickness_layer, 0);
405 new G4PVPlacement(0, G4ThreeVector(0, 0, (tower_readout_dz) / 2.0 - clamp_plate_width),
406 single_tower_replica_logic,
407 "replicated_layers_placed",
412 if (nFibers > 0 && nFibers == 5 && fiber_diam > 0)
414 std::string fiberName =
"single_fiber_scintillator_solid" +
std::to_string(type);
415 G4VSolid* single_scintillator_solid =
new G4Tubs(fiberName,
416 0.0, fiber_diam / 2.0, (
m_TowerDz[2] + fiber_extra_length) / 2, 0.0, 2 *
M_PI);
421 std::string fiberLogicName =
"hEcal_scintillator_fiber_logic" +
std::to_string(type);
422 G4LogicalVolume* single_scintillator_logic =
new G4LogicalVolume(single_scintillator_solid,
431 new G4PVPlacement(0, G4ThreeVector(0, 0, -fiber_extra_length / 2 + tower_readout_dz / 2 - clamp_plate_width),
432 single_scintillator_logic,
433 name_scintillator +
"_center",
437 new G4PVPlacement(0, G4ThreeVector(-
m_TowerDx[2] / 4.0,
m_TowerDy[2] / 4.0, -fiber_extra_length / 2 + tower_readout_dz / 2 - clamp_plate_width),
438 single_scintillator_logic,
439 name_scintillator +
"_tl",
443 new G4PVPlacement(0, G4ThreeVector(
m_TowerDx[2] / 4.0, -
m_TowerDy[2] / 4.0, -fiber_extra_length / 2 + tower_readout_dz / 2 - clamp_plate_width),
444 single_scintillator_logic,
445 name_scintillator +
"_bl",
449 new G4PVPlacement(0, G4ThreeVector(
m_TowerDx[2] / 4.0,
m_TowerDy[2] / 4.0, -fiber_extra_length / 2 + tower_readout_dz / 2 - clamp_plate_width),
450 single_scintillator_logic,
451 name_scintillator +
"_tr",
455 new G4PVPlacement(0, G4ThreeVector(-
m_TowerDx[2] / 4.0, -
m_TowerDy[2] / 4.0, -fiber_extra_length / 2 + tower_readout_dz / 2 - clamp_plate_width),
456 single_scintillator_logic,
457 name_scintillator +
"_br",
464 std::cout <<
"PHG4ForwardEcalDetector: Building logical volume for single tower done." << std::endl;
467 return single_tower_logic;
477 std::cout <<
"PHG4ForwardEcalDetector: Place tower " << iterator->first
478 <<
" idx_j = " << iterator->second.idx_j <<
", idx_k = " << iterator->second.idx_k
479 <<
" at x = " << iterator->second.x <<
" , y = " << iterator->second.y <<
" , z = " << iterator->second.z << std::endl;
482 assert(iterator->second.type >= 0 && iterator->second.type <= 6);
483 G4LogicalVolume* singletower = singletowerIn[iterator->second.type];
484 int copyno = (iterator->second.idx_j << 16) + iterator->second.idx_k;
486 G4PVPlacement* tower_placement =
487 new G4PVPlacement(0, G4ThreeVector(iterator->second.x, iterator->second.y, iterator->second.z),
504 G4Material* material_ScintFEMC =
new G4Material(
"PolystyreneFEMC", density = 1.03 *
g /
cm3, ncomponents = 2);
510 const G4int ntab = 4;
512 G4double wls_Energy[] = {2.00 *
eV, 2.87 *
eV, 2.90 *
eV,
515 G4double rIndexPstyrene[] = {1.5, 1.5, 1.5, 1.5};
516 G4double absorption1[] = {2. *
cm, 2. *
cm, 2. *
cm, 2. *
cm};
517 G4double scintilFast[] = {0.0, 0.0, 1.0, 1.0};
518 G4MaterialPropertiesTable* fMPTPStyrene =
new G4MaterialPropertiesTable();
519 fMPTPStyrene->AddProperty(
"RINDEX", wls_Energy, rIndexPstyrene, ntab);
520 fMPTPStyrene->AddProperty(
"ABSLENGTH", wls_Energy, absorption1, ntab);
521 fMPTPStyrene->AddProperty(
"SCINTILLATIONCOMPONENT1", wls_Energy, scintilFast, ntab);
522 fMPTPStyrene->AddConstProperty(
"SCINTILLATIONYIELD", 10. /
keV);
523 fMPTPStyrene->AddConstProperty(
"RESOLUTIONSCALE", 1.0);
524 fMPTPStyrene->AddConstProperty(
"SCINTILLATIONTIMECONSTANT", 10. *
ns);
526 material_ScintFEMC->SetMaterialPropertiesTable(fMPTPStyrene);
529 material_ScintFEMC->GetIonisation()->SetBirksConstant(0.126 *
mm /
MeV);
531 return material_ScintFEMC;
540 G4double density, fractionmass;
542 G4Material* material_TiO2 =
new G4Material(
"TiO2_FEMC", density = 1.52 *
g /
cm3, ncomponents = 2);
550 density = 1.86 *
g /
cm3;
551 G4Material* Coating_FEMC =
new G4Material(
"Coating_FEMC", density, ncomponents = 2);
553 Coating_FEMC->AddMaterial(material_TiO2, fractionmass = 0.20);
561 G4OpticalSurface*
surface =
new G4OpticalSurface(
"ScintWrapB1");
563 new G4LogicalSkinSurface(
"CrystalSurfaceL", vol, surface);
565 surface->SetType(dielectric_metal);
566 surface->SetFinish(polished);
567 surface->SetModel(glisur);
576 G4MaterialPropertiesTable* surfmat =
new G4MaterialPropertiesTable();
579 surface->SetMaterialPropertiesTable(surfmat);
588 std::cout <<
"PHG4ForwardEcalDetector: Making WLSFiberFEMC material..." << std::endl;
594 G4Material* material_WLSFiberFEMC =
new G4Material(
"WLSFiberFEMC", density = 1.18 *
g /
cm3, ncomponents = 3);
600 const G4int ntab = 4;
601 G4double wls_Energy[] = {2.00 *
eV, 2.87 *
eV, 2.90 *
eV,
604 G4double RefractiveIndexFiber[] = {1.6, 1.6, 1.6, 1.6};
605 G4double AbsFiber[] = {9.0 *
m, 9.0 *
m, 0.1 *
mm, 0.1 *
mm};
606 G4double EmissionFib[] = {1.0, 1.0, 0.0, 0.0};
608 G4MaterialPropertiesTable* mptWLSfiber =
new G4MaterialPropertiesTable();
609 mptWLSfiber->AddProperty(
"RINDEX", wls_Energy, RefractiveIndexFiber, ntab);
610 mptWLSfiber->AddProperty(
"WLSABSLENGTH", wls_Energy, AbsFiber, ntab);
611 mptWLSfiber->AddProperty(
"WLSCOMPONENT", wls_Energy, EmissionFib, ntab);
612 mptWLSfiber->AddConstProperty(
"WLSTIMECONSTANT", 0.5 *
ns);
613 material_WLSFiberFEMC->SetMaterialPropertiesTable(mptWLSfiber);
617 std::cout <<
"PHG4ForwardEcalDetector: Making WLSFiberFEMC material done." << std::endl;
620 return material_WLSFiberFEMC;
626 std::ifstream istream_mapping;
628 if (!istream_mapping.is_open())
630 std::cout <<
"ERROR in PHG4ForwardEcalDetector: Failed to open mapping file " <<
m_Params->
get_string_param(
"mapping_file") << std::endl;
635 std::string line_mapping;
636 while (
getline(istream_mapping, line_mapping))
639 if (line_mapping.find(
"#") != std::string::npos)
643 std::cout <<
"PHG4ForwardEcalDetector: SKIPPING line in mapping file: " << line_mapping << std::endl;
648 std::istringstream iss(line_mapping);
651 if (line_mapping.find(
"Tower ") != std::string::npos)
653 unsigned idx_j, idx_k, idx_l;
654 G4double pos_x, pos_y, pos_z;
655 G4double size_x, size_y,
size_z;
656 G4double rot_x, rot_y, rot_z;
661 if (!(iss >> dummys >> type >> idx_j >> idx_k >> idx_l >> pos_x >> pos_y >> pos_z >> size_x >> size_y >> size_z >> rot_x >> rot_y >> rot_z))
663 std::cout <<
"ERROR in PHG4ForwardEcalDetector: Failed to read line in mapping file " <<
m_Params->
get_string_param(
"mapping_file") << std::endl;
669 std::ostringstream towername;
681 tower_new.
idx_j = idx_j;
682 tower_new.
idx_k = idx_k;
693 if (!(iss >> parname >> parval))
695 std::cout <<
"ERROR in PHG4ForwardEcalDetector: Failed to read line in mapping file " <<
m_Params->
get_string_param(
"mapping_file") << std::endl;
703 std::map<std::string, double>::iterator parit;
704 std::ostringstream twr;
705 for (
int i = 0; i < 7; i++)
708 twr <<
"Gtower" << i <<
"_dx";
712 twr <<
"Gtower" << i <<
"_dy";
716 twr <<
"Gtower" << i <<
"_dz";
720 std::ostringstream
rad;
721 for (
int i = 0; i < 2; i++)
725 rad <<
"Gr" << index <<
"_inner";
732 rad <<
"Gr" << index <<
"_outer";
742 m_dZ = parit->second *
cm;
809 assert(type >= 0 && type <= 6);