18 #include <Geant4/G4Box.hh>
19 #include <Geant4/G4DisplacedSolid.hh>
20 #include <Geant4/G4Exception.hh>
21 #include <Geant4/G4ExceptionSeverity.hh>
22 #include <Geant4/G4LogicalVolume.hh>
23 #include <Geant4/G4Material.hh>
24 #include <Geant4/G4PVPlacement.hh>
25 #include <Geant4/G4PhysicalConstants.hh>
26 #include <Geant4/G4String.hh>
27 #include <Geant4/G4SystemOfUnits.hh>
28 #include <Geant4/G4ThreeVector.hh>
29 #include <Geant4/G4Transform3D.hh>
30 #include <Geant4/G4Trap.hh>
31 #include <Geant4/G4Types.hh>
32 #include <Geant4/G4Vector3D.hh>
36 #include <boost/foreach.hpp>
61 assert(
_geom ==
nullptr);
67 <<
"PHG4FullProjTiltedSpacalDetector::Constructor - Fatal Error - invalid geometry object!"
84 cout <<
"PHG4FullProjTiltedSpacalDetector::Construct::" <<
GetName()
85 <<
" - start with PHG4SpacalDetector::Construct()." << endl;
92 cout <<
"PHG4FullProjTiltedSpacalDetector::Construct::" <<
GetName()
93 <<
" - Completed." << endl;
97 std::pair<G4LogicalVolume*, G4Transform3D>
107 const G4double half_chord_backend =
110 const G4double reduced_outer_radius = sqrt(pow(
get_geom_v3()->get_max_radius() *
cm, 2) - half_chord_backend * half_chord_backend);
113 const G4double enclosure_half_height_half_width = enclosure_center * tan(
pi /
get_geom_v3()->get_azimuthal_n_sec());
115 const G4double width_adj1 = tan(
get_geom_v3()->get_azimuthal_tilt() -
pi /
get_geom_v3()->get_azimuthal_n_sec()) * enclosure_depth * 0.5;
116 const G4double width_adj2 = tan(
get_geom_v3()->get_azimuthal_tilt() +
pi /
get_geom_v3()->get_azimuthal_n_sec()) * enclosure_depth * 0.5;
118 const G4double center_adj = (width_adj1 + width_adj2) * 0.5;
119 const G4double center_tilt_angle = atan2(center_adj, enclosure_depth * 0.5);
120 const G4double inner_half_width = enclosure_half_height_half_width + 0.5 * (width_adj1 - width_adj2);
121 const G4double outter_half_width = enclosure_half_height_half_width + 0.5 * (-width_adj1 + width_adj2);
124 const G4double edge1_tilt_angle = atan2(width_adj1, enclosure_depth * 0.5);
125 const G4double edge2_tilt_angle = atan2(width_adj2, enclosure_depth * 0.5);
126 const G4double edge1_half_depth = sqrt(width_adj1 * width_adj1 + enclosure_depth * enclosure_depth * .25);
127 const G4double edge2_half_depth = sqrt(width_adj2 * width_adj2 + enclosure_depth * enclosure_depth * .25);
130 const G4double half_projection_ratio = 0.5 * (-width_adj1 + width_adj2) / enclosure_half_height_half_width;
131 const G4double projection_center_y = enclosure_center - ((enclosure_depth * 0.5) / half_projection_ratio);
132 const G4double projection_center_x = center_adj / half_projection_ratio;
136 assert(phi_bin_in_sec >= 1);
137 const G4double block_azimuth_angle = (edge2_tilt_angle - edge1_tilt_angle) / phi_bin_in_sec;
138 assert(block_azimuth_angle > 0);
146 G4double block_width_ratio = 0;
147 for (
int s = 0;
s < phi_bin_in_sec; ++
s)
149 block_width_ratio += 1 /
cos(block_azimuth_angle * (0.5 +
s) + edge1_tilt_angle);
151 const G4double block_half_height_width = (block_edge1_half_width + block_edge2_half_width) / block_width_ratio;
152 assert(block_half_height_width > 0);
156 struct block_azimuth_geom
159 G4double projection_center_y;
160 G4double projection_center_x;
161 G4double projection_length;
163 vector<block_azimuth_geom> block_azimuth_geoms(phi_bin_in_sec,
165 numeric_limits<double>::signaling_NaN(),
166 numeric_limits<double>::signaling_NaN(),
167 numeric_limits<double>::signaling_NaN(),
168 numeric_limits<double>::signaling_NaN()});
169 G4double block_x_edge1 = block_edge1_half_width;
170 for (
int s = 0;
s < phi_bin_in_sec; ++
s)
172 block_azimuth_geom& geom = block_azimuth_geoms[
s];
174 geom.angle = block_azimuth_angle * (0.5 +
s) + edge1_tilt_angle;
175 const G4double block_x_size = block_half_height_width /
cos(geom.angle);
176 assert(block_x_size > 0);
177 const G4double x_center = block_x_edge1 - 0.5 * block_x_size;
180 geom.projection_length = block_half_height_width / 2. / tan(block_azimuth_angle / 2.);
181 assert(geom.projection_length > 0);
182 geom.projection_center_y = enclosure_center - geom.projection_length *
cos(geom.angle);
183 geom.projection_center_x = x_center + geom.projection_length * sin(geom.angle);
186 block_x_edge1 -= block_x_size;
190 struct block_divider_azimuth_geom
193 G4double projection_center_y;
194 G4double projection_center_x;
196 G4double radial_displacement;
199 assert(phi_bin_in_sec >= 1);
200 vector<block_divider_azimuth_geom> divider_azimuth_geoms(phi_bin_in_sec - 1,
201 block_divider_azimuth_geom{
202 numeric_limits<double>::signaling_NaN(),
203 numeric_limits<double>::signaling_NaN(),
204 numeric_limits<double>::signaling_NaN(),
205 numeric_limits<double>::signaling_NaN(),
206 numeric_limits<double>::signaling_NaN(),
207 numeric_limits<double>::signaling_NaN()});
211 for (
int s = 0;
s < phi_bin_in_sec - 1; ++
s)
213 block_divider_azimuth_geom& geom = divider_azimuth_geoms[
s];
215 geom.angle = 0.5 * (block_azimuth_geoms[
s].angle + block_azimuth_geoms[
s + 1].angle);
216 geom.projection_center_y = 0.5 * (block_azimuth_geoms[
s].projection_center_y + block_azimuth_geoms[
s + 1].projection_center_y);
217 geom.projection_center_x = 0.5 * (block_azimuth_geoms[
s].projection_center_x + block_azimuth_geoms[
s + 1].projection_center_x);
218 geom.radial_displacement = 0.5 * (block_azimuth_geoms[
s].projection_length + block_azimuth_geoms[
s + 1].projection_length);
225 if (fabs(block_x_edge1 - (-block_edge2_half_width)) >
get_geom_v3()->get_assembly_spacing() *
cm)
227 cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg - ERROR - " << endl
228 <<
"\t block_x_edge1 = " << block_x_edge1 << endl
229 <<
"\t block_edge2_half_width = " << block_edge2_half_width << endl
230 <<
"\t fabs(block_x_edge1 - (-block_edge2_half_width)) = " << fabs(block_x_edge1 - (-block_edge2_half_width)) << endl
233 if (!(fabs(block_x_edge1 - (-block_edge2_half_width)) <
get_geom_v3()->get_assembly_spacing() *
cm))
235 cout <<
"closure check failed: " << fabs(block_x_edge1 - (-block_edge2_half_width)) << endl;
241 cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg - " << endl
242 <<
"\t edge1_tilt_angle = " << edge1_tilt_angle << endl
243 <<
"\t edge2_tilt_angle = " << edge2_tilt_angle << endl
244 <<
"\t projection_center_y = " << projection_center_y << endl
245 <<
"\t projection_center_x = " << projection_center_x << endl
246 <<
"\t block_azimuth_angle = " << block_azimuth_angle << endl
247 <<
"\t block_edge1_half_width = " << block_edge1_half_width << endl
248 <<
"\t block_edge2_half_width = " << block_edge2_half_width << endl
249 <<
"\t block_width_ratio = " << block_width_ratio << endl
250 <<
"\t block_half_height_width = " << block_half_height_width << endl;
252 for (
int s = 0;
s < phi_bin_in_sec; ++
s)
254 cout <<
"\t block[" <<
s <<
"].angle = " << block_azimuth_geoms[
s].angle << endl;
255 cout <<
"\t block[" <<
s <<
"].projection_center_y = " << block_azimuth_geoms[
s].projection_center_y << endl;
256 cout <<
"\t block[" <<
s <<
"].projection_center_x = " << block_azimuth_geoms[
s].projection_center_x << endl;
258 for (
int s = 0;
s < phi_bin_in_sec - 1; ++
s)
260 cout <<
"\t divider[" <<
s <<
"].angle = " << divider_azimuth_geoms[
s].angle << endl;
261 cout <<
"\t divider[" <<
s <<
"].projection_center_x = " << divider_azimuth_geoms[
s].projection_center_x << endl;
262 cout <<
"\t divider[" <<
s <<
"].projection_center_y = " << divider_azimuth_geoms[
s].projection_center_y << endl;
263 cout <<
"\t divider[" <<
s <<
"].radial_displacement = " << divider_azimuth_geoms[
s].radial_displacement << endl;
264 cout <<
"\t divider[" <<
s <<
"].thickness = " << divider_azimuth_geoms[
s].thickness << endl;
265 cout <<
"\t divider[" <<
s <<
"].width = " << divider_azimuth_geoms[
s].width << endl;
269 assert(enclosure_depth > 10 *
cm);
271 G4VSolid* sec_solid =
new G4Trap(
272 G4String(
GetName() +
string(
"_sec_trap")),
273 enclosure_depth * 0.5,
274 center_tilt_angle, halfpi,
280 G4Transform3D sec_solid_transform = G4TranslateY3D(enclosure_center) * G4RotateY3D(halfpi) * G4RotateX3D(-halfpi);
281 G4VSolid* sec_solid_place =
new G4DisplacedSolid(G4String(
GetName() +
string(
"_sec")), sec_solid, sec_solid_transform);
285 assert(cylinder_mat);
287 G4LogicalVolume* sec_logic =
new G4LogicalVolume(sec_solid_place, cylinder_mat,
288 G4String(G4String(
GetName() +
string(
"_sec"))), 0, 0,
nullptr);
300 if (
get_geom_v3()->get_construction_verbose() >= 1)
302 cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg::" <<
GetName()
303 <<
" - construct end walls." << endl;
312 G4VSolid* wall_solid =
new G4Trap(G4String(
GetName() +
string(
"_EndWall_trap")),
313 enclosure_depth * 0.5,
314 center_tilt_angle, halfpi,
315 inner_half_width, side_wall_half_thickness, side_wall_half_thickness,
317 outter_half_width, side_wall_half_thickness, side_wall_half_thickness,
320 G4VSolid* wall_solid_place =
new G4DisplacedSolid(G4String(
GetName() +
string(
"_EndWall")), wall_solid, sec_solid_transform);
322 G4LogicalVolume* wall_logic =
new G4LogicalVolume(wall_solid_place, wall_mat,
323 G4String(G4String(
GetName() +
string(
"_EndWall"))), 0, 0,
327 typedef map<int, double> z_locations_t;
328 z_locations_t z_locations;
336 if (
get_geom_v3()->get_construction_verbose() >= 2)
338 cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg::"
339 <<
GetName() <<
" - constructed End Wall ID " << val.first
340 <<
" @ Z = " << val.second << endl;
342 G4Transform3D wall_trans = G4TranslateZ3D(val.second);
344 G4PVPlacement* wall_phys =
new G4PVPlacement(wall_trans, wall_logic,
345 G4String(
GetName()) + G4String(
"_EndWall_") +
to_string(val.first), sec_logic,
357 if (
get_geom_v3()->get_construction_verbose() >= 1)
359 cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg::" <<
GetName()
360 <<
" - construct side walls." << endl;
363 typedef map<int, pair<int, int> > sign_t;
365 signs[100] = make_pair(+1, +1);
366 signs[101] = make_pair(+1, -1);
367 signs[200] = make_pair(-1, +1);
368 signs[201] = make_pair(-1, -1);
372 const int sign_z = val.second.first;
373 const int sign_azimuth = val.second.second;
375 if (
get_geom_v3()->get_construction_verbose() >= 2)
377 cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg::"
378 <<
GetName() <<
" - constructed Side Wall ID " << val.first
387 const G4double azimuth_roate = sign_azimuth > 0 ? edge1_tilt_angle : edge2_tilt_angle;
390 G4Box* wall_solid =
new G4Box(G4String(
GetName() + G4String(
"_SideWall_") +
to_string(val.first)),
395 G4LogicalVolume* wall_logic =
new G4LogicalVolume(wall_solid, wall_mat,
396 G4String(G4String(
GetName() + G4String(
"_SideWall_") +
to_string(val.first))), 0, 0,
400 const G4Transform3D wall_trans =
401 G4TranslateZ3D(sign_z * (
get_geom_v3()->get_length() *
cm / 4)) *
402 G4TranslateY3D(enclosure_center) *
403 G4TranslateX3D(sign_azimuth * enclosure_half_height_half_width) *
404 G4RotateZ3D(azimuth_roate) *
405 G4TranslateX3D(-sign_azimuth * (
get_geom_v3()->get_sidewall_thickness() *
cm / 2.0 +
get_geom_v3()->get_sidewall_outer_torr() *
cm));
407 G4PVPlacement* wall_phys =
new G4PVPlacement(wall_trans, wall_logic,
408 G4String(
GetName()) + G4String(
"_SideWall_") +
to_string(val.first), sec_logic,
420 if (
get_geom_v3()->get_construction_verbose() >= 1)
422 cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg::" <<
GetName()
423 <<
" - construct dividers" << endl;
430 for (
const auto& geom : divider_azimuth_geoms)
432 G4Box* divider_solid =
new G4Box(G4String(
GetName() + G4String(
"_Divider_") +
to_string(ID)),
433 geom.thickness / 2.0,
437 G4LogicalVolume* wall_logic =
new G4LogicalVolume(divider_solid, divider_mat,
438 G4String(G4String(
GetName() + G4String(
"_Divider_") +
to_string(ID))), 0, 0,
442 for (
int sign_z = -1; sign_z <= 1; sign_z += 2)
444 G4Transform3D wall_trans =
445 G4TranslateX3D(geom.projection_center_x) *
446 G4TranslateY3D(geom.projection_center_y) *
447 G4RotateZ3D(geom.angle) *
448 G4TranslateY3D(geom.radial_displacement) *
449 G4TranslateZ3D(sign_z * (
get_geom_v3()->get_length() *
cm / 4));
451 G4PVPlacement* wall_phys =
new G4PVPlacement(wall_trans, wall_logic,
461 cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg - placing divider " << wall_phys->GetName() <<
" copy ID " << ID << endl;
475 const int tower_id = g_tower.
id;
476 const int tower_phi_id_in_sec = tower_id % 10;
477 assert(tower_phi_id_in_sec >= 0);
478 assert(tower_phi_id_in_sec < phi_bin_in_sec);
480 const auto& block_azimuth_geom = block_azimuth_geoms.at(tower_phi_id_in_sec);
484 G4Transform3D block_trans =
485 G4TranslateX3D(block_azimuth_geom.projection_center_x) *
486 G4TranslateY3D(block_azimuth_geom.projection_center_y) *
487 G4RotateZ3D(block_azimuth_geom.angle) *
495 G4PVPlacement* block_phys =
new G4PVPlacement(block_trans, LV_tower,
497 g_tower.
id, overlapcheck_block);
506 for (
int ix = 0; ix < g_tower.
NSubtowerX; ix++)
509 for (
int iy = 0; iy < g_tower.
NSubtowerY; iy++)
515 G4PVPlacement* lg_phys =
new G4PVPlacement(block_trans, LV_lg, LV_lg->GetName(),
516 sec_logic,
false, g_tower.
id, overlapcheck_block);
518 block_vol[lg_phys] = g_tower.
id * 100 + ix * 10 + iy;
527 cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg::" <<
GetName()
529 <<
" unique towers" << endl;
531 return make_pair(sec_logic, G4Transform3D::Identity);
537 G4LogicalVolume* LV_tower)
543 typedef map<int, pair<G4Vector3D, G4Vector3D> > fiber_par_map;
544 fiber_par_map fiber_par;
545 G4double min_fiber_length = g_tower.
pDz *
cm * 4;
547 G4Vector3D v_zshift = G4Vector3D(tan(g_tower.
pTheta) *
cos(g_tower.
pPhi),
551 for (
int ix = 0; ix < g_tower.
NFiberX; ix++)
554 const double weighted_ix =
static_cast<double>(ix) / (g_tower.
NFiberX - 1.);
562 for (
int iy = 0; iy < g_tower.
NFiberY; iy++)
565 if ((ix + iy) % 2 == 1)
568 const double weighted_iy =
static_cast<double>(iy) / (g_tower.
NFiberY - 1.);
573 const double weighted_pDx12 = weighted_pDx1 * (1 - weighted_iy) + weighted_pDx2 * (weighted_iy) + weighted_pDy1 * tan(g_tower.
pAlp1);
574 const double weighted_pDx34 = weighted_pDx3 * (1 - weighted_iy) + weighted_pDx4 * (weighted_iy) + weighted_pDy1 * tan(g_tower.
pAlp2);
576 G4Vector3D
v1 = G4Vector3D(weighted_pDx12, weighted_pDy1, 0) - v_zshift;
577 G4Vector3D
v2 = G4Vector3D(weighted_pDx34, weighted_pDy2, 0) + v_zshift;
579 G4Vector3D vector_fiber = (v2 -
v1);
581 G4Vector3D center_fiber = (v2 +
v1) / 2;
588 fiber_par[fiber_ID] = make_pair(vector_fiber,
591 const G4double fiber_length = vector_fiber.mag();
593 min_fiber_length =
min(fiber_length, min_fiber_length);
601 const G4double fiber_length = min_fiber_length;
602 vector<G4double> fiber_cut;
605 ss << string(
"_Tower") << g_tower.
id;
606 G4LogicalVolume* fiber_logic =
Construct_Fiber(fiber_length, ss.str());
610 const int fiber_ID = val.first;
611 G4Vector3D vector_fiber = val.second.first;
612 G4Vector3D center_fiber = val.second.second;
613 const G4double optimal_fiber_length = vector_fiber.mag();
615 const G4Vector3D
v1 = center_fiber - 0.5 * vector_fiber;
618 assert(optimal_fiber_length - fiber_length >= 0);
619 fiber_cut.push_back(optimal_fiber_length - fiber_length);
621 center_fiber += (fiber_length / optimal_fiber_length - 1) * 0.5 * vector_fiber;
622 vector_fiber *= fiber_length / optimal_fiber_length;
627 cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_Fibers_SameLengthFiberPerTower::" <<
GetName()
628 <<
" - constructed fiber " << fiber_ID << ss.str()
629 <<
", Length = " << optimal_fiber_length <<
"-"
630 << (optimal_fiber_length - fiber_length) <<
"mm, "
631 <<
"x = " << center_fiber.x() <<
"mm, "
632 <<
"y = " << center_fiber.y() <<
"mm, "
633 <<
"z = " << center_fiber.z() <<
"mm, "
634 <<
"vx = " << vector_fiber.x() <<
"mm, "
635 <<
"vy = " << vector_fiber.y() <<
"mm, "
636 <<
"vz = " << vector_fiber.z() <<
"mm, "
639 const G4double rotation_angle = G4Vector3D(0, 0, 1).angle(vector_fiber);
640 const G4Vector3D rotation_axis =
641 rotation_angle == 0 ? G4Vector3D(1, 0, 0) : G4Vector3D(0, 0, 1).cross(vector_fiber);
643 G4Transform3D fiber_place(
644 G4Translate3D(center_fiber.x(), center_fiber.y(), center_fiber.z()) * G4Rotate3D(rotation_angle, rotation_axis));
647 name <<
GetName() + string(
"_Tower") << g_tower.
id <<
"_fiber"
651 G4PVPlacement* fiber_physi =
new G4PVPlacement(fiber_place, fiber_logic,
652 G4String(name.str()), LV_tower,
false, fiber_ID,
661 if (
get_geom_v3()->get_construction_verbose() >= 2)
663 <<
"PHG4FullProjTiltedSpacalDetector::Construct_Fibers_SameLengthFiberPerTower::"
664 <<
GetName() <<
" - constructed tower ID " << g_tower.
id <<
" with "
665 << fiber_count <<
" fibers. Average fiber length cut = "
666 << accumulate(fiber_cut.begin(), fiber_cut.end(), 0.0) / fiber_cut.size() <<
" mm" << endl;
674 G4LogicalVolume* LV_tower)
676 G4Vector3D v_zshift = G4Vector3D(tan(g_tower.
pTheta) *
cos(g_tower.
pPhi),
680 for (
int ix = 0; ix < g_tower.
NFiberX; ix++)
682 const double weighted_ix =
static_cast<double>(ix) / (g_tower.
NFiberX - 1.);
690 for (
int iy = 0; iy < g_tower.
NFiberY; iy++)
692 if ((ix + iy) % 2 == 1)
696 const double weighted_iy =
static_cast<double>(iy) / (g_tower.
NFiberY - 1.);
701 const double weighted_pDx12 = weighted_pDx1 * (1 - weighted_iy) + weighted_pDx2 * (weighted_iy) + weighted_pDy1 * tan(g_tower.
pAlp1);
702 const double weighted_pDx34 = weighted_pDx3 * (1 - weighted_iy) + weighted_pDx4 * (weighted_iy) + weighted_pDy1 * tan(g_tower.
pAlp2);
704 G4Vector3D
v1 = G4Vector3D(weighted_pDx12, weighted_pDy1, 0) - v_zshift;
705 G4Vector3D
v2 = G4Vector3D(weighted_pDx34, weighted_pDy2, 0) + v_zshift;
707 G4Vector3D vector_fiber = (v2 -
v1);
709 G4Vector3D center_fiber = (v2 +
v1) / 2;
715 const G4double fiber_length = vector_fiber.mag();
718 ss << string(
"_Tower") << g_tower.
id;
725 cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_Fibers::" <<
GetName()
726 <<
" - constructed fiber " << fiber_ID << ss.str()
727 <<
", Length = " << fiber_length <<
"mm, "
728 <<
"x = " << center_fiber.x() <<
"mm, "
729 <<
"y = " << center_fiber.y() <<
"mm, "
730 <<
"z = " << center_fiber.z() <<
"mm, "
731 <<
"vx = " << vector_fiber.x() <<
"mm, "
732 <<
"vy = " << vector_fiber.y() <<
"mm, "
733 <<
"vz = " << vector_fiber.z() <<
"mm, "
736 const G4double rotation_angle = G4Vector3D(0, 0, 1).angle(
738 const G4Vector3D rotation_axis =
739 rotation_angle == 0 ? G4Vector3D(1, 0, 0) : G4Vector3D(0, 0, 1).cross(vector_fiber);
741 G4Transform3D fiber_place(
742 G4Translate3D(center_fiber.x(), center_fiber.y(),
744 G4Rotate3D(rotation_angle, rotation_axis));
747 name <<
GetName() + string(
"_Tower") << g_tower.
id <<
"_fiber"
751 G4PVPlacement* fiber_physi =
new G4PVPlacement(fiber_place,
752 fiber_logic, G4String(name.str()), LV_tower,
false,
753 fiber_ID, overlapcheck_fiber);
762 if (
get_geom_v3()->get_construction_verbose() >= 3)
763 cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_Fibers::" <<
GetName()
764 <<
" - constructed tower ID " << g_tower.
id <<
" with " << fiber_cnt
765 <<
" fibers" << endl;
775 std::stringstream sout;
776 sout <<
"_" << g_tower.
id;
777 const G4String sTowerID(sout.str());
781 G4Trap* block_solid =
new G4Trap(
782 G4String(
GetName()) + sTowerID,
792 assert(cylinder_mat);
794 G4LogicalVolume* block_logic =
new G4LogicalVolume(block_solid, cylinder_mat,
795 G4String(G4String(
GetName()) +
string(
"_Tower") + sTowerID), 0, 0,
808 if (
get_geom_v3()->get_construction_verbose() >= 2)
809 cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_Tower::" <<
GetName()
810 <<
" - constructed tower ID " << g_tower.
id <<
" with "
811 << fiber_count <<
" fibers using Construct_Fibers" << endl;
818 if (
get_geom_v3()->get_construction_verbose() >= 2)
819 cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_Tower::" <<
GetName()
820 <<
" - constructed tower ID " << g_tower.
id <<
" with "
822 <<
" fibers using Construct_Fibers_SameLengthFiberPerTower."
823 <<
"V = " << block_solid->GetCubicVolume() / (
cm3) <<
"cm3, "
824 <<
"m = " << block_logic->GetMass() / gram <<
"gram, "
825 <<
"Density = " << (block_logic->GetMass() / gram) / (block_solid->GetCubicVolume() /
cm3) <<
"g/cm3"
830 G4ExceptionDescription message;
833 G4Exception(
"PHG4FullProjTiltedSpacalDetector::Construct_Tower",
"Wrong",
834 FatalException, message,
"");
843 const int index_x,
const int index_y)
846 std::stringstream sout;
847 sout <<
"_Lightguide_" << g_tower.
id <<
"_" << index_x <<
"_" << index_y;
848 const G4String sTowerID(sout.str());
853 const double weight_x1 = 1 - (double) index_y / g_tower.
NSubtowerY;
854 const double weight_x2 = 1 - (
double) (index_y + 1) / g_tower.
NSubtowerY;
855 const double weight_xcenter = 1 - (
double) (index_y + 0.5) / g_tower.
NSubtowerY;
857 assert(weight_x1 >= 0 and weight_x1 <= 1);
858 assert(weight_x2 >= 0 and weight_x2 <= 1);
859 assert(weight_xcenter >= 0 and weight_xcenter <= 1);
861 const double lg_pDx1 = (g_tower.
pDx1 * weight_x1
862 + g_tower.
pDx2 * (1 - weight_x1)) /
864 const double lg_pDx2 = (g_tower.
pDx1 * weight_x2
865 + g_tower.
pDx2 * (1 - weight_x2)) /
868 const double lg_Alp1 = atan(
871 const double shift_xcenter = (g_tower.
pDx1 * weight_xcenter
872 + g_tower.
pDx2 * (1 - weight_xcenter))
875 const double shift_ycenter = g_tower.
pDy1
879 G4VSolid* block_solid =
new G4Trap(
880 G4String(
GetName()) + sTowerID,
887 lg_pDy1 * cm, lg_pDx1 * cm, lg_pDx2 * cm,
891 block_solid =
new G4DisplacedSolid(G4String(
GetName() +
"_displaced"),
895 tan(g_tower.
pTheta * rad) * sin(g_tower.
pPhi * rad),
899 + G4ThreeVector(shift_xcenter * cm, shift_ycenter * cm, 0)
904 assert(cylinder_mat);
906 G4LogicalVolume* block_logic =
new G4LogicalVolume(block_solid, cylinder_mat,
907 G4String(G4String(
GetName()) +
string(
"_Tower") + sTowerID), 0, 0,
918 cout <<
"PHG4FullProjTiltedSpacalDetector::Print::" <<
GetName()
919 <<
" - Print Geometry:" << endl;