16 #include <Geant4/G4Box.hh>
17 #include <Geant4/G4DisplacedSolid.hh>
18 #include <Geant4/G4Exception.hh>
19 #include <Geant4/G4ExceptionSeverity.hh>
20 #include <Geant4/G4IntersectionSolid.hh>
21 #include <Geant4/G4LogicalVolume.hh>
22 #include <Geant4/G4PVPlacement.hh>
23 #include <Geant4/G4PhysicalConstants.hh>
24 #include <Geant4/G4Sphere.hh>
25 #include <Geant4/G4String.hh>
26 #include <Geant4/G4SystemOfUnits.hh>
27 #include <Geant4/G4ThreeVector.hh>
28 #include <Geant4/G4Transform3D.hh>
29 #include <Geant4/G4Tubs.hh>
30 #include <Geant4/G4Types.hh>
42 : overlapcheck_sector(
false)
52 if (geom.get_total_thickness() == 0)
55 (
std::string(
"PHG4SectorConstructor::Construct_Sectors::") + (name_base)).c_str(),
56 __FILE__, FatalException,
57 " detector configured with zero thickness!");
60 if (geom.get_min_polar_angle() == geom.get_max_polar_angle())
63 (
std::string(
"PHG4SectorConstructor::Construct_Sectors::") + (name_base)).c_str(),
64 __FILE__, FatalException,
"min_polar_angle = max_polar_angle!");
66 if (geom.get_min_polar_angle() > geom.get_max_polar_angle())
69 (
std::string(
"PHG4SectorConstructor::Construct_Sectors::") + (name_base)).c_str(),
70 __FILE__, JustWarning,
71 "min and max polar angle got reversed. Correcting them.");
73 const double t = geom.get_max_polar_angle();
74 geom.set_max_polar_angle(geom.get_min_polar_angle());
75 geom.set_min_polar_angle(t);
80 (
std::string(
"PHG4SectorConstructor::Construct_Sectors::") + (name_base)).c_str(),
81 __FILE__, FatalException,
82 "can NOT use flat edge for single or double sector detector!");
85 const G4Transform3D transform_Det_to_Hall =
86 G4RotateX3D(-geom.get_normal_polar_angle()) * G4TranslateZ3D(
87 geom.get_normal_start() + geom.get_total_thickness() / 2);
89 const G4Transform3D transform_Hall_to_Det(transform_Det_to_Hall.inverse());
93 static const double epsilon = std::numeric_limits<float>::epsilon();
94 const double sph_min_polar_angle =
96 const double sph_max_polar_angle =
99 G4VSolid *SecConeBoundary_Hall =
new G4Sphere(
"SecConeBoundary_Hall",
100 geom.get_normal_start(), geom.get_max_R(),
101 pi / 2 -
pi / geom.get_N_Sector(), 2 *
pi / geom.get_N_Sector(),
102 sph_min_polar_angle, sph_max_polar_angle - sph_min_polar_angle
105 G4VSolid *SecConeBoundary_Det =
new G4DisplacedSolid(
"SecConeBoundary_Det",
106 SecConeBoundary_Hall, transform_Hall_to_Det);
108 G4VSolid *Boundary_Det = SecConeBoundary_Det;
114 const double sph_min_polar_size =
115 (geom.get_min_polar_edge() ==
Sector_Geometry::kConeEdge) ? geom.get_max_R() : geom.get_normal_start() * tan(geom.get_normal_polar_angle() - geom.get_min_polar_angle());
116 const double sph_max_polar_size =
117 (geom.get_max_polar_edge() ==
Sector_Geometry::kConeEdge) ? geom.get_max_R() : geom.get_normal_start() * tan(geom.get_max_polar_angle() - geom.get_normal_polar_angle());
119 G4VSolid *BoxBoundary_Det =
new G4Box(
"BoxBoundary_Det",
120 geom.get_max_R(), (sph_min_polar_size + sph_max_polar_size) / 2,
121 geom.get_total_thickness());
122 G4VSolid *BoxBoundary_Det_Place =
new G4DisplacedSolid(
123 "BoxBoundary_Det_Place", BoxBoundary_Det,
nullptr,
124 G4ThreeVector(0, (sph_max_polar_size - sph_min_polar_size) / 2, 0));
126 Boundary_Det =
new G4IntersectionSolid(
"Boundary_Det",
127 BoxBoundary_Det_Place, SecConeBoundary_Det);
130 G4VSolid *DetectorBox_Det = Construct_Sectors_Plane(
"DetectorBox_Det",
131 -geom.get_total_thickness() / 2, geom.get_total_thickness(),
136 G4LogicalVolume *DetectorLog_Det =
new G4LogicalVolume(DetectorBox_Det,
137 p_mat, name_base +
"_Log");
138 RegisterLogicalVolume(DetectorLog_Det);
140 for (G4int sec = 0; sec < geom.get_N_Sector(); sec++)
142 RegisterPhysicalVolume(
144 G4RotateZ3D(2 *
pi / geom.get_N_Sector() * sec) * transform_Det_to_Hall, DetectorLog_Det,
145 name_base +
"_Physical", WorldLog,
false, sec, overlapcheck_sector));
149 double z_start = -geom.get_total_thickness() / 2;
151 for (
const auto &l : geom.layer_list)
153 if (l.percentage_filled > 100. || l.percentage_filled < 0)
155 std::ostringstream strstr;
156 strstr << name_base <<
" have invalid layer ";
157 strstr << l.name <<
" with percentage_filled =" << l.percentage_filled;
160 (
std::string(
"PHG4SectorConstructor::Construct_Sectors::") + (name_base)).c_str(), __FILE__, FatalException,
161 strstr.str().c_str());
164 const std::string layer_name = name_base +
"_" + l.name;
166 G4VSolid *LayerSol_Det = Construct_Sectors_Plane(layer_name +
"_Sol",
167 z_start, l.depth * l.percentage_filled * perCent, Boundary_Det);
169 G4LogicalVolume *LayerLog_Det =
new G4LogicalVolume(LayerSol_Det,
171 RegisterLogicalVolume(LayerLog_Det);
173 RegisterPhysicalVolume(
174 new G4PVPlacement(
nullptr, G4ThreeVector(), LayerLog_Det,
175 layer_name +
"_Physical", DetectorLog_Det,
false, 0, overlapcheck_sector),
181 if (std::abs(z_start - geom.get_total_thickness() / 2) > 1 *
um)
183 std::ostringstream strstr;
184 strstr << name_base <<
" - accumulated thickness = "
185 << (z_start + geom.get_total_thickness() / 2) /
um
186 <<
" um expected thickness = " << geom.get_total_thickness() /
um
189 (
std::string(
"PHG4SectorConstructor::Construct_Sectors::") + (name_base)).c_str(),
190 __FILE__, FatalException, strstr.str().c_str());
193 m_DisplayAction->AddVolume(DetectorLog_Det,
"DetectorBox");
196 std::cout <<
"PHG4SectorConstructor::Construct_Sectors::" << name_base
197 <<
" - total thickness = " << geom.get_total_thickness() /
cm <<
" cm"
199 std::cout <<
"PHG4SectorConstructor::Construct_Sectors::" << name_base <<
" - "
200 << map_log_vol.size() <<
" logical volume constructed" << std::endl;
201 std::cout <<
"PHG4SectorConstructor::Construct_Sectors::" << name_base <<
" - "
202 << map_phy_vol.size() <<
" physical volume constructed; "
203 << map_active_phy_vol.size() <<
" is active." << std::endl;
210 const double start_z,
212 G4VSolid *SecConeBoundary_Det
215 assert(SecConeBoundary_Det);
217 G4VSolid *Sol_Raw =
new G4Tubs(name +
"_Raw",
225 G4VSolid *Sol_Place =
new G4DisplacedSolid(name +
"_Place", Sol_Raw,
nullptr,
226 G4ThreeVector(0, 0, start_z + thickness / 2));
228 G4VSolid *Sol =
new G4IntersectionSolid(name, Sol_Place,
229 SecConeBoundary_Det);
241 normal_polar_angle = 0;
244 min_polar_angle = .1;
247 max_polar_angle = .3;
250 normal_start = 305 *
cm;
252 min_polar_edge = kConeEdge;
254 max_polar_edge = kConeEdge;
263 <<
"PHG4SectorConstructor::RegisterVolume - Error - invalid volume!"
267 if (map_log_vol.find(v->GetName()) != map_log_vol.end())
269 std::cout <<
"PHG4SectorConstructor::RegisterVolume - Warning - replacing "
270 << v->GetName() << std::endl;
273 map_log_vol[v->GetName()] =
v;
285 <<
"PHG4SectorConstructor::RegisterPhysicalVolume - Error - invalid volume!"
292 if (map_phy_vol.find(
id) != map_phy_vol.end())
295 <<
"PHG4SectorConstructor::RegisterPhysicalVolume - Warning - replacing "
296 << v->GetName() <<
"[" << v->GetCopyNo() <<
"]" << std::endl;
302 map_active_phy_vol[
id] =
v;
311 for (
const auto &
it : layer_list)
322 assert(std::abs(min_polar_angle - normal_polar_angle) <
pi / 2);
323 assert(std::abs(max_polar_angle - normal_polar_angle) <
pi / 2);
328 if (cos(min_polar_angle + normal_polar_angle) <= 0)
330 std::stringstream strstr;
331 strstr <<
"Geometry check failed. " << std::endl;
332 strstr <<
"normal_polar_angle = " << normal_polar_angle << std::endl;
333 strstr <<
"min_polar_angle = " << min_polar_angle << std::endl;
334 strstr <<
"max_polar_angle = " << max_polar_angle << std::endl;
335 strstr <<
"cos(min_polar_angle + normal_polar_angle) = "
336 << cos(min_polar_angle + normal_polar_angle) << std::endl;
338 G4Exception(
"Sector_Geometry::get_max_R", __FILE__, FatalException,
339 strstr.str().c_str());
341 if (cos(max_polar_angle + normal_polar_angle) <= 0)
343 std::stringstream strstr;
344 strstr <<
"Geometry check failed. " << std::endl;
345 strstr <<
"normal_polar_angle = " << normal_polar_angle << std::endl;
346 strstr <<
"min_polar_angle = " << min_polar_angle << std::endl;
347 strstr <<
"max_polar_angle = " << max_polar_angle << std::endl;
348 strstr <<
"cos(max_polar_angle + normal_polar_angle) = "
349 << cos(max_polar_angle + normal_polar_angle) << std::endl;
351 G4Exception(
"Sector_Geometry::get_max_R", __FILE__, FatalException,
352 strstr.str().c_str());
355 const double max_tan_angle = std::max(
356 std::abs(tan(min_polar_angle + normal_polar_angle)),
357 std::abs(tan(max_polar_angle + normal_polar_angle)));
359 return (get_normal_start() + get_total_thickness()) * sqrt(1 + max_tan_angle * max_tan_angle);
363 const double max_angle = std::max(
364 std::abs(min_polar_angle - normal_polar_angle),
365 std::abs(max_polar_angle - normal_polar_angle));
367 return (get_normal_start() + get_total_thickness()) * sqrt(1 + pow(tan(max_angle), 2) + pow(tan(2 *
pi / N_Sector), 2)) * 2;
379 AddLayer(
"EntranceWindow",
"G4_MYLAR", 25 *
um,
false, 100);
380 AddLayer(
"Cathode",
"G4_GRAPHITE", 10 *
um,
false, 100);
381 AddLayer(
"DrftVol",
material, drift_vol_thickness,
true, 100);
401 for (
int gem = 1; gem <= n_GEM_layers; gem++)
403 std::stringstream
sid;
407 AddLayer(G4String(
"GEMFrontCu") + G4String(sid.str()),
"G4_Cu",
408 0.0005 *
cm,
false, 64);
411 AddLayer(G4String(
"GEMKapton") + G4String(sid.str()),
"G4_KAPTON",
412 0.005 *
cm,
false, 64);
415 AddLayer(G4String(
"GEMBackCu") + G4String(sid.str()),
"G4_Cu",
416 0.0005 *
cm,
false, 64);
419 AddLayer(G4String(
"Frame") + G4String(sid.str()),
"G10", 0.15 *
cm,
false,
424 AddLayer(G4String(
"PCBKapton"),
"G4_KAPTON", 0.005 *
cm,
false, 100);
427 AddLayer(G4String(
"PCBCu"),
"G4_Cu", 0.0005 *
cm,
false, 80);
430 AddLayer(
"Facesheet",
"G10", 0.025 * 2 *
cm,
false, 100);
446 AddLayer(G4String(
"ReadoutFR4"),
"G10", 0.05 *
cm,
false, 100);
447 AddLayer(G4String(
"ReadoutCu"),
"G4_Cu", 0.001 *
cm,
false, 100);
451 AddLayer(G4String(
"SocketsCu"),
"G4_Cu", 0.0005 *
cm,
false, 100);
459 const double expansion_length,
std::string radiator)
461 if (radiator ==
"Default")
463 radiator =
"ePHENIX_AeroGel";
467 AddLayer(
"EntranceWindow",
"G10", 0.05 *
cm,
false, 100);
468 AddLayer(
"AeroGel", radiator, radiator_length,
false, 100);
469 AddLayer(
"ExpansionVol",
"G4_AIR", expansion_length,
false, 100);
472 AddLayer(G4String(
"ReadoutFR4"),
"G10", 0.05 *
cm,
false, 100);
473 AddLayer(G4String(
"ReadoutCu"),
"G4_Cu", 0.001 *
cm,
false, 100);
474 AddLayer(G4String(
"SocketsCu"),
"G4_Cu", 0.0005 *
cm,
false, 100);