18 #include <phparameter/PHParameters.h>
20 #include <Geant4/G4Box.hh>
21 #include <Geant4/G4DisplacedSolid.hh>
22 #include <Geant4/G4Exception.hh>
23 #include <Geant4/G4ExceptionSeverity.hh>
24 #include <Geant4/G4LogicalVolume.hh>
25 #include <Geant4/G4PVPlacement.hh>
26 #include <Geant4/G4PhysicalConstants.hh>
27 #include <Geant4/G4String.hh>
28 #include <Geant4/G4SystemOfUnits.hh>
29 #include <Geant4/G4ThreeVector.hh>
30 #include <Geant4/G4Transform3D.hh>
31 #include <Geant4/G4Trap.hh>
32 #include <Geant4/G4Types.hh>
33 #include <Geant4/G4Vector3D.hh>
58 , m_Params(parameters)
66 <<
"PHG4FullProjTiltedSpacalDetector::Constructor - Fatal Error - invalid geometry object!"
83 std::cout <<
"PHG4FullProjTiltedSpacalDetector::Construct::" <<
GetName()
84 <<
" - start with PHG4SpacalDetector::Construct()." << std::endl;
91 std::cout <<
"PHG4FullProjTiltedSpacalDetector::Construct::" <<
GetName()
92 <<
" - Completed." << std::endl;
101 catch (std::exception&
e)
103 std::cout << e.what() << std::endl;
108 std::pair<G4LogicalVolume*, G4Transform3D>
118 const G4double half_chord_backend =
121 const G4double reduced_outer_radius = sqrt(pow(
get_geom_v3()->get_max_radius() *
cm, 2) - half_chord_backend * half_chord_backend);
124 const G4double enclosure_half_height_half_width = enclosure_center * tan(
pi /
get_geom_v3()->get_azimuthal_n_sec());
126 const G4double width_adj1 = tan(
get_geom_v3()->get_azimuthal_tilt() -
pi /
get_geom_v3()->get_azimuthal_n_sec()) * enclosure_depth * 0.5;
127 const G4double width_adj2 = tan(
get_geom_v3()->get_azimuthal_tilt() +
pi /
get_geom_v3()->get_azimuthal_n_sec()) * enclosure_depth * 0.5;
129 const G4double center_adj = (width_adj1 + width_adj2) * 0.5;
130 const G4double center_tilt_angle = atan2(center_adj, enclosure_depth * 0.5);
131 const G4double inner_half_width = enclosure_half_height_half_width + 0.5 * (width_adj1 - width_adj2);
132 const G4double outter_half_width = enclosure_half_height_half_width + 0.5 * (-width_adj1 + width_adj2);
135 const G4double edge1_tilt_angle = atan2(width_adj1, enclosure_depth * 0.5);
136 const G4double edge2_tilt_angle = atan2(width_adj2, enclosure_depth * 0.5);
137 const G4double edge1_half_depth = sqrt(width_adj1 * width_adj1 + enclosure_depth * enclosure_depth * .25);
138 const G4double edge2_half_depth = sqrt(width_adj2 * width_adj2 + enclosure_depth * enclosure_depth * .25);
141 const G4double half_projection_ratio = 0.5 * (-width_adj1 + width_adj2) / enclosure_half_height_half_width;
142 const G4double projection_center_y = enclosure_center - ((enclosure_depth * 0.5) / half_projection_ratio);
143 const G4double projection_center_x = center_adj / half_projection_ratio;
147 assert(phi_bin_in_sec >= 1);
148 const G4double block_azimuth_angle = (edge2_tilt_angle - edge1_tilt_angle) / phi_bin_in_sec;
149 assert(block_azimuth_angle > 0);
150 if (!(fabs(block_azimuth_angle - M_PI * 2 /
get_geom_v3()->get_azimuthal_n_sec() / phi_bin_in_sec) < M_PI * std::numeric_limits<G4double>::epsilon()))
152 std::cout <<
"angle/nsec out of range: " << M_PI * std::numeric_limits<G4double>::epsilon() << std::endl;
157 G4double block_width_ratio = 0;
158 for (
int sa = 0; sa < phi_bin_in_sec; ++sa)
160 block_width_ratio += 1 / cos(block_azimuth_angle * (0.5 + sa) + edge1_tilt_angle);
162 const G4double block_half_height_width = (block_edge1_half_width + block_edge2_half_width) / block_width_ratio;
163 assert(block_half_height_width > 0);
167 struct block_azimuth_geom
170 G4double projection_center_y;
171 G4double projection_center_x;
172 G4double projection_length;
174 std::vector<block_azimuth_geom> block_azimuth_geoms(phi_bin_in_sec,
176 std::numeric_limits<double>::quiet_NaN(),
177 std::numeric_limits<double>::quiet_NaN(),
178 std::numeric_limits<double>::quiet_NaN(),
179 std::numeric_limits<double>::quiet_NaN()});
180 G4double block_x_edge1 = block_edge1_half_width;
181 for (
int sa = 0; sa < phi_bin_in_sec; ++sa)
183 block_azimuth_geom& geom = block_azimuth_geoms[sa];
185 geom.angle = block_azimuth_angle * (0.5 + sa) + edge1_tilt_angle;
186 const G4double block_x_size = block_half_height_width / cos(geom.angle);
188 const G4double x_center = block_x_edge1 - 0.5 * block_x_size;
191 geom.projection_length = block_half_height_width / 2. / tan(block_azimuth_angle / 2.);
192 assert(geom.projection_length > 0);
193 geom.projection_center_y = enclosure_center - geom.projection_length * cos(geom.angle);
194 geom.projection_center_x = x_center + geom.projection_length * sin(geom.angle);
197 block_x_edge1 -= block_x_size;
201 struct block_divider_azimuth_geom
204 G4double projection_center_y;
205 G4double projection_center_x;
207 G4double radial_displacement;
210 assert(phi_bin_in_sec >= 1);
211 std::vector<block_divider_azimuth_geom> divider_azimuth_geoms(phi_bin_in_sec - 1,
212 block_divider_azimuth_geom{
213 std::numeric_limits<double>::quiet_NaN(),
214 std::numeric_limits<double>::quiet_NaN(),
215 std::numeric_limits<double>::quiet_NaN(),
216 std::numeric_limits<double>::quiet_NaN(),
217 std::numeric_limits<double>::quiet_NaN(),
218 std::numeric_limits<double>::quiet_NaN()});
222 for (
int sa = 0; sa < phi_bin_in_sec - 1; ++sa)
224 block_divider_azimuth_geom& geom = divider_azimuth_geoms[sa];
226 geom.angle = 0.5 * (block_azimuth_geoms[sa].angle + block_azimuth_geoms[sa + 1].angle);
227 geom.projection_center_y = 0.5 * (block_azimuth_geoms[sa].projection_center_y + block_azimuth_geoms[sa + 1].projection_center_y);
228 geom.projection_center_x = 0.5 * (block_azimuth_geoms[sa].projection_center_x + block_azimuth_geoms[sa + 1].projection_center_x);
229 geom.radial_displacement = 0.5 * (block_azimuth_geoms[sa].projection_length + block_azimuth_geoms[sa + 1].projection_length);
236 if (fabs(block_x_edge1 - (-block_edge2_half_width)) >
get_geom_v3()->get_assembly_spacing() *
cm)
238 std::cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg - ERROR - " << std::endl
239 <<
"\t block_x_edge1 = " << block_x_edge1 << std::endl
240 <<
"\t block_edge2_half_width = " << block_edge2_half_width << std::endl
241 <<
"\t fabs(block_x_edge1 - (-block_edge2_half_width)) = " << fabs(block_x_edge1 - (-block_edge2_half_width)) << std::endl
244 if (!(fabs(block_x_edge1 - (-block_edge2_half_width)) <
get_geom_v3()->get_assembly_spacing() *
cm))
246 std::cout <<
"closure check failed: " << fabs(block_x_edge1 - (-block_edge2_half_width)) << std::endl;
252 std::cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg - " << std::endl
253 <<
"\t edge1_tilt_angle = " << edge1_tilt_angle << std::endl
254 <<
"\t edge2_tilt_angle = " << edge2_tilt_angle << std::endl
255 <<
"\t projection_center_y = " << projection_center_y << std::endl
256 <<
"\t projection_center_x = " << projection_center_x << std::endl
257 <<
"\t block_azimuth_angle = " << block_azimuth_angle << std::endl
258 <<
"\t block_edge1_half_width = " << block_edge1_half_width << std::endl
259 <<
"\t block_edge2_half_width = " << block_edge2_half_width << std::endl
260 <<
"\t block_width_ratio = " << block_width_ratio << std::endl
261 <<
"\t block_half_height_width = " << block_half_height_width << std::endl;
263 for (
int sa = 0; sa < phi_bin_in_sec; ++sa)
265 std::cout <<
"\t block[" << sa <<
"].angle = " << block_azimuth_geoms[sa].angle << std::endl;
266 std::cout <<
"\t block[" << sa <<
"].projection_center_y = " << block_azimuth_geoms[sa].projection_center_y << std::endl;
267 std::cout <<
"\t block[" << sa <<
"].projection_center_x = " << block_azimuth_geoms[sa].projection_center_x << std::endl;
269 for (
int sa = 0; sa < phi_bin_in_sec - 1; ++sa)
271 std::cout <<
"\t divider[" << sa <<
"].angle = " << divider_azimuth_geoms[sa].angle << std::endl;
272 std::cout <<
"\t divider[" << sa <<
"].projection_center_x = " << divider_azimuth_geoms[sa].projection_center_x << std::endl;
273 std::cout <<
"\t divider[" << sa <<
"].projection_center_y = " << divider_azimuth_geoms[sa].projection_center_y << std::endl;
274 std::cout <<
"\t divider[" << sa <<
"].radial_displacement = " << divider_azimuth_geoms[sa].radial_displacement << std::endl;
275 std::cout <<
"\t divider[" << sa <<
"].thickness = " << divider_azimuth_geoms[sa].thickness << std::endl;
276 std::cout <<
"\t divider[" << sa <<
"].width = " << divider_azimuth_geoms[sa].width << std::endl;
282 G4VSolid* sec_solid =
new G4Trap(
284 enclosure_depth * 0.5,
285 center_tilt_angle, halfpi,
291 G4Transform3D sec_solid_transform = G4TranslateY3D(enclosure_center) * G4RotateY3D(halfpi) * G4RotateX3D(-halfpi);
292 G4VSolid* sec_solid_place =
new G4DisplacedSolid(G4String(
GetName() +
std::string(
"_sec")), sec_solid, sec_solid_transform);
298 G4LogicalVolume* sec_logic =
new G4LogicalVolume(sec_solid_place, cylinder_mat,
311 if (
get_geom_v3()->get_construction_verbose() >= 1)
313 std::cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg::" <<
GetName()
314 <<
" - construct end walls." << std::endl;
324 enclosure_depth * 0.5,
325 center_tilt_angle, halfpi,
326 inner_half_width, side_wall_half_thickness, side_wall_half_thickness,
328 outter_half_width, side_wall_half_thickness, side_wall_half_thickness,
331 G4VSolid* wall_solid_place =
new G4DisplacedSolid(G4String(
GetName() +
std::string(
"_EndWall")), wall_solid, sec_solid_transform);
333 G4LogicalVolume* wall_logic =
new G4LogicalVolume(wall_solid_place, wall_mat,
338 using z_locations_t = std::map<int, double>;
339 z_locations_t z_locations;
349 std::cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg::"
350 <<
GetName() <<
" - constructed End Wall ID " << val.first
351 <<
" @ Z = " << val.second << std::endl;
353 G4Transform3D wall_trans = G4TranslateZ3D(val.second);
355 G4PVPlacement* wall_phys =
new G4PVPlacement(wall_trans, wall_logic,
368 if (
get_geom_v3()->get_construction_verbose() >= 1)
370 std::cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg::" <<
GetName()
371 <<
" - construct side walls." << std::endl;
374 using sign_t = std::map<int, std::pair<int, int>>;
376 signs[100] = std::make_pair(+1, +1);
377 signs[101] = std::make_pair(+1, -1);
378 signs[200] = std::make_pair(-1, +1);
379 signs[201] = std::make_pair(-1, -1);
383 const int sign_z = val.second.first;
384 const int sign_azimuth = val.second.second;
386 if (
get_geom_v3()->get_construction_verbose() >= 2)
388 std::cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg::"
389 <<
GetName() <<
" - constructed Side Wall ID " << val.first
398 const G4double azimuth_roate = sign_azimuth > 0 ? edge1_tilt_angle : edge2_tilt_angle;
401 G4Box* wall_solid =
new G4Box(G4String(
GetName() + G4String(
"_SideWall_") +
std::to_string(val.first)),
406 G4LogicalVolume* wall_logic =
new G4LogicalVolume(wall_solid, wall_mat,
407 G4String(G4String(
GetName() + G4String(
"_SideWall_") +
std::to_string(val.first))),
nullptr,
nullptr,
411 const G4Transform3D wall_trans =
412 G4TranslateZ3D(sign_z * (
get_geom_v3()->get_length() *
cm / 4)) *
413 G4TranslateY3D(enclosure_center) *
414 G4TranslateX3D(sign_azimuth * enclosure_half_height_half_width) *
415 G4RotateZ3D(azimuth_roate) *
416 G4TranslateX3D(-sign_azimuth * (
get_geom_v3()->get_sidewall_thickness() *
cm / 2.0 +
get_geom_v3()->get_sidewall_outer_torr() *
cm));
418 G4PVPlacement* wall_phys =
new G4PVPlacement(wall_trans, wall_logic,
431 if (
get_geom_v3()->get_construction_verbose() >= 1)
433 std::cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg::" <<
GetName()
434 <<
" - construct dividers" << std::endl;
441 for (
const auto& geom : divider_azimuth_geoms)
444 geom.thickness / 2.0,
448 G4LogicalVolume* wall_logic =
new G4LogicalVolume(divider_solid, divider_mat,
453 for (
int sign_z = -1; sign_z <= 1; sign_z += 2)
455 G4Transform3D wall_trans =
456 G4TranslateX3D(geom.projection_center_x) *
457 G4TranslateY3D(geom.projection_center_y) *
458 G4RotateZ3D(geom.angle) *
459 G4TranslateY3D(geom.radial_displacement) *
460 G4TranslateZ3D(sign_z * (
get_geom_v3()->get_length() *
cm / 4));
462 G4PVPlacement* wall_phys =
new G4PVPlacement(wall_trans, wall_logic,
472 std::cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg - placing divider " << wall_phys->GetName() <<
" copy ID " << ID << std::endl;
486 const int tower_id = g_tower.
id;
487 const int tower_phi_id_in_sec = tower_id % 10;
488 assert(tower_phi_id_in_sec >= 0);
489 assert(tower_phi_id_in_sec < phi_bin_in_sec);
491 const auto& block_azimuth_geom = block_azimuth_geoms.at(tower_phi_id_in_sec);
495 G4Transform3D block_trans =
496 G4TranslateX3D(block_azimuth_geom.projection_center_x) *
497 G4TranslateY3D(block_azimuth_geom.projection_center_y) *
498 G4RotateZ3D(block_azimuth_geom.angle) *
506 G4PVPlacement* block_phys =
new G4PVPlacement(block_trans, LV_tower,
508 g_tower.
id, overlapcheck_block);
517 for (
int ix = 0; ix < g_tower.
NSubtowerX; ix++)
520 for (
int iy = 0; iy < g_tower.
NSubtowerY; iy++)
526 G4PVPlacement* lg_phys =
new G4PVPlacement(block_trans, LV_lg, LV_lg->GetName(),
527 sec_logic,
false, g_tower.
id, overlapcheck_block);
529 block_vol[lg_phys] = g_tower.
id * 100 + ix * 10 + iy;
538 std::cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_AzimuthalSeg::" <<
GetName()
540 <<
" unique towers" << std::endl;
542 return std::make_pair(sec_logic, G4Transform3D::Identity);
548 G4LogicalVolume* LV_tower)
554 using fiber_par_map = std::map<int, std::pair<G4Vector3D, G4Vector3D>>;
555 fiber_par_map fiber_par;
556 G4double min_fiber_length = g_tower.
pDz *
cm * 4;
558 G4Vector3D v_zshift = G4Vector3D(tan(g_tower.
pTheta) * cos(g_tower.
pPhi),
562 for (
int ix = 0; ix < g_tower.
NFiberX; ix++)
565 const double weighted_ix =
static_cast<double>(ix) / (g_tower.
NFiberX - 1.);
573 for (
int iy = 0; iy < g_tower.
NFiberY; iy++)
576 if ((ix + iy) % 2 == 1)
579 const double weighted_iy =
static_cast<double>(iy) / (g_tower.
NFiberY - 1.);
584 const double weighted_pDx12 = weighted_pDx1 * (1 - weighted_iy) + weighted_pDx2 * (weighted_iy) + weighted_pDy1 * tan(g_tower.
pAlp1);
585 const double weighted_pDx34 = weighted_pDx3 * (1 - weighted_iy) + weighted_pDx4 * (weighted_iy) + weighted_pDy1 * tan(g_tower.
pAlp2);
587 G4Vector3D
v1 = G4Vector3D(weighted_pDx12, weighted_pDy1, 0) - v_zshift;
588 G4Vector3D
v2 = G4Vector3D(weighted_pDx34, weighted_pDy2, 0) + v_zshift;
590 G4Vector3D vector_fiber = (v2 -
v1);
592 G4Vector3D center_fiber = (v2 +
v1) / 2;
599 fiber_par[fiber_ID] = std::make_pair(vector_fiber,
602 const G4double fiber_length = vector_fiber.mag();
604 min_fiber_length =
std::min(fiber_length, min_fiber_length);
612 const G4double fiber_length = min_fiber_length;
613 std::vector<G4double> fiber_cut;
615 std::stringstream ss;
617 G4LogicalVolume* fiber_logic =
Construct_Fiber(fiber_length, ss.str());
621 const int fiber_ID = val.first;
622 G4Vector3D vector_fiber = val.second.first;
623 G4Vector3D center_fiber = val.second.second;
624 const G4double optimal_fiber_length = vector_fiber.mag();
626 const G4Vector3D
v1 = center_fiber - 0.5 * vector_fiber;
629 assert(optimal_fiber_length - fiber_length >= 0);
630 fiber_cut.push_back(optimal_fiber_length - fiber_length);
632 center_fiber += (fiber_length / optimal_fiber_length - 1) * 0.5 * vector_fiber;
633 vector_fiber *= fiber_length / optimal_fiber_length;
638 std::cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_Fibers_SameLengthFiberPerTower::" <<
GetName()
639 <<
" - constructed fiber " << fiber_ID << ss.str()
640 <<
", Length = " << optimal_fiber_length <<
"-"
641 << (optimal_fiber_length - fiber_length) <<
"mm, "
642 <<
"x = " << center_fiber.x() <<
"mm, "
643 <<
"y = " << center_fiber.y() <<
"mm, "
644 <<
"z = " << center_fiber.z() <<
"mm, "
645 <<
"vx = " << vector_fiber.x() <<
"mm, "
646 <<
"vy = " << vector_fiber.y() <<
"mm, "
647 <<
"vz = " << vector_fiber.z() <<
"mm, "
650 const G4double rotation_angle = G4Vector3D(0, 0, 1).angle(vector_fiber);
651 const G4Vector3D rotation_axis =
652 rotation_angle == 0 ? G4Vector3D(1, 0, 0) : G4Vector3D(0, 0, 1).cross(vector_fiber);
654 G4Transform3D fiber_place(
655 G4Translate3D(center_fiber.x(), center_fiber.y(), center_fiber.z()) * G4Rotate3D(rotation_angle, rotation_axis));
657 std::stringstream
name;
662 G4PVPlacement* fiber_physi =
new G4PVPlacement(fiber_place, fiber_logic,
663 G4String(name.str()), LV_tower,
false, fiber_ID,
672 if (
get_geom_v3()->get_construction_verbose() >= 2)
674 <<
"PHG4FullProjTiltedSpacalDetector::Construct_Fibers_SameLengthFiberPerTower::"
675 <<
GetName() <<
" - constructed tower ID " << g_tower.
id <<
" with "
676 << fiber_count <<
" fibers. Average fiber length cut = "
677 << std::accumulate(fiber_cut.begin(), fiber_cut.end(), 0.0) / fiber_cut.size() <<
" mm" << std::endl;
685 G4LogicalVolume* LV_tower)
687 G4Vector3D v_zshift = G4Vector3D(tan(g_tower.
pTheta) * cos(g_tower.
pPhi),
691 for (
int ix = 0; ix < g_tower.
NFiberX; ix++)
693 const double weighted_ix =
static_cast<double>(ix) / (g_tower.
NFiberX - 1.);
701 for (
int iy = 0; iy < g_tower.
NFiberY; iy++)
703 if ((ix + iy) % 2 == 1)
707 const double weighted_iy =
static_cast<double>(iy) / (g_tower.
NFiberY - 1.);
712 const double weighted_pDx12 = weighted_pDx1 * (1 - weighted_iy) + weighted_pDx2 * (weighted_iy) + weighted_pDy1 * tan(g_tower.
pAlp1);
713 const double weighted_pDx34 = weighted_pDx3 * (1 - weighted_iy) + weighted_pDx4 * (weighted_iy) + weighted_pDy1 * tan(g_tower.
pAlp2);
715 G4Vector3D
v1 = G4Vector3D(weighted_pDx12, weighted_pDy1, 0) - v_zshift;
716 G4Vector3D
v2 = G4Vector3D(weighted_pDx34, weighted_pDy2, 0) + v_zshift;
718 G4Vector3D vector_fiber = (v2 -
v1);
720 G4Vector3D center_fiber = (v2 +
v1) / 2;
726 const G4double fiber_length = vector_fiber.mag();
728 std::stringstream ss;
736 std::cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_Fibers::" <<
GetName()
737 <<
" - constructed fiber " << fiber_ID << ss.str()
738 <<
", Length = " << fiber_length <<
"mm, "
739 <<
"x = " << center_fiber.x() <<
"mm, "
740 <<
"y = " << center_fiber.y() <<
"mm, "
741 <<
"z = " << center_fiber.z() <<
"mm, "
742 <<
"vx = " << vector_fiber.x() <<
"mm, "
743 <<
"vy = " << vector_fiber.y() <<
"mm, "
744 <<
"vz = " << vector_fiber.z() <<
"mm, "
747 const G4double rotation_angle = G4Vector3D(0, 0, 1).angle(
749 const G4Vector3D rotation_axis =
750 rotation_angle == 0 ? G4Vector3D(1, 0, 0) : G4Vector3D(0, 0, 1).cross(vector_fiber);
752 G4Transform3D fiber_place(
753 G4Translate3D(center_fiber.x(), center_fiber.y(),
755 G4Rotate3D(rotation_angle, rotation_axis));
757 std::stringstream
name;
762 G4PVPlacement* fiber_physi =
new G4PVPlacement(fiber_place,
763 fiber_logic, G4String(name.str()), LV_tower,
false,
764 fiber_ID, overlapcheck_fiber);
773 if (
get_geom_v3()->get_construction_verbose() >= 3)
774 std::cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_Fibers::" <<
GetName()
775 <<
" - constructed tower ID " << g_tower.
id <<
" with " << fiber_cnt
776 <<
" fibers" << std::endl;
786 std::stringstream sout;
787 sout <<
"_" << g_tower.
id;
788 const G4String sTowerID(sout.str());
792 G4Trap* block_solid =
new G4Trap(
793 G4String(
GetName()) + sTowerID,
805 G4LogicalVolume* block_logic =
new G4LogicalVolume(block_solid, cylinder_mat,
817 if (
get_geom_v3()->get_construction_verbose() >= 2)
818 std::cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_Tower::" <<
GetName()
819 <<
" - constructed tower ID " << g_tower.
id <<
" with "
820 << fiber_count <<
" fibers using Construct_Fibers" << std::endl;
827 if (
get_geom_v3()->get_construction_verbose() >= 2)
828 std::cout <<
"PHG4FullProjTiltedSpacalDetector::Construct_Tower::" <<
GetName()
829 <<
" - constructed tower ID " << g_tower.
id <<
" with "
831 <<
" fibers using Construct_Fibers_SameLengthFiberPerTower."
832 <<
"V = " << block_solid->GetCubicVolume() / (
cm3) <<
"cm3, "
833 <<
"m = " << block_logic->GetMass() / gram <<
"gram, "
834 <<
"Density = " << (block_logic->GetMass() / gram) / (block_solid->GetCubicVolume() /
cm3) <<
"g/cm3"
839 G4ExceptionDescription
message;
842 G4Exception(
"PHG4FullProjTiltedSpacalDetector::Construct_Tower",
"Wrong",
843 FatalException, message,
"");
852 const int index_x,
const int index_y)
855 std::stringstream sout;
856 sout <<
"_Lightguide_" << g_tower.
id <<
"_" << index_x <<
"_" << index_y;
857 const G4String sTowerID(sout.str());
863 const double weight_x2 = 1 - (
double) (index_y + 1) / g_tower.
NSubtowerY;
864 const double weight_xcenter = 1 - (
double) (index_y + 0.5) / g_tower.
NSubtowerY;
866 assert(weight_x1 >= 0 and weight_x1 <= 1);
867 assert(weight_x2 >= 0 and weight_x2 <= 1);
868 assert(weight_xcenter >= 0 and weight_xcenter <= 1);
870 const double lg_pDx1 = (g_tower.
pDx1 * weight_x1
871 + g_tower.
pDx2 * (1 - weight_x1)) /
873 const double lg_pDx2 = (g_tower.
pDx1 * weight_x2
874 + g_tower.
pDx2 * (1 - weight_x2)) /
877 const double lg_Alp1 = atan(
880 const double shift_xcenter = (g_tower.
pDx1 * weight_xcenter
881 + g_tower.
pDx2 * (1 - weight_xcenter))
884 const double shift_ycenter = g_tower.
pDy1
888 G4VSolid* block_solid =
new G4Trap(
889 G4String(
GetName()) + sTowerID,
896 lg_pDy1 * cm, lg_pDx1 * cm, lg_pDx2 * cm,
900 block_solid =
new G4DisplacedSolid(G4String(
GetName() +
"_displaced"),
901 block_solid,
nullptr,
903 tan(g_tower.
pTheta * rad) * cos(g_tower.
pPhi * rad),
904 tan(g_tower.
pTheta * rad) * sin(g_tower.
pPhi * rad),
908 + G4ThreeVector(shift_xcenter * cm, shift_ycenter * cm, 0)
915 G4LogicalVolume* block_logic =
new G4LogicalVolume(block_solid, cylinder_mat,
927 std::cout <<
"PHG4FullProjTiltedSpacalDetector::Print::" <<
GetName()
928 <<
" - Print Geometry:" << std::endl;