6 #include <phparameter/PHParameters.h>
19 #include <Geant4/G4Box.hh>
20 #include <Geant4/G4DisplacedSolid.hh>
21 #include <Geant4/G4LogicalVolume.hh>
22 #include <Geant4/G4Material.hh>
23 #include <Geant4/G4PVPlacement.hh>
24 #include <Geant4/G4PhysicalConstants.hh>
25 #include <Geant4/G4String.hh>
26 #include <Geant4/G4SubtractionSolid.hh>
27 #include <Geant4/G4SystemOfUnits.hh>
28 #include <Geant4/G4ThreeVector.hh>
29 #include <Geant4/G4Transform3D.hh>
30 #include <Geant4/G4Trap.hh>
31 #include <Geant4/G4Tubs.hh>
32 #include <Geant4/G4Types.hh>
33 #include <Geant4/G4UserLimits.hh>
34 #include <Geant4/G4Vector3D.hh>
35 #include <Geant4/G4VisAttributes.hh>
37 #include <boost/foreach.hpp>
56 , construction_params(parameters)
57 , cylinder_solid(nullptr)
58 , cylinder_logic(nullptr)
59 , cylinder_physi(nullptr)
65 , clading_step_limits(nullptr)
66 , fiber_core_step_limits(nullptr)
111 "PHCompositeNode",
"RUN"));
139 "z_rotation_degree") *
145 "enclosure_x_shift") *
170 cylinder_solid =
new G4DisplacedSolid(G4String(
GetName() +
"_displaced"),
172 G4ThreeVector(box_x_shift, 0, box_z_shift));
174 G4Material* cylinder_mat = G4Material::GetMaterial(
"G4_AIR");
177 cylinder_logic =
new G4LogicalVolume(cylinder_solid, cylinder_mat,
179 G4VisAttributes* VisAtt =
new G4VisAttributes();
181 VisAtt->SetVisibility(
true);
182 VisAtt->SetForceSolid(
186 G4Transform3D cylinder_place(
189 * G4RotateZ3D(z_rotation)
199 G4LogicalVolume* sec_logic = psec.first;
200 const G4Transform3D& sec_trans = psec.second;
203 const int sec = val.first;
204 const double rot = val.second;
206 G4Transform3D sec_place = G4RotateZ3D(rot) * sec_trans;
209 name <<
GetName() <<
"_sec" << sec;
211 G4PVPlacement* calo_phys =
new G4PVPlacement(sec_place, sec_logic,
220 "electronics_thickness") *
223 "electronics_material");
225 G4VSolid* electronics_solid =
new G4Box(G4String(
GetName()),
226 electronics_thickness / 2.0,
232 electronics_solid =
new G4DisplacedSolid(G4String(
GetName() +
"_displaced"),
239 electronics_thickness,
242 G4Material* electronics_mat = G4Material::GetMaterial(electronics_material);
245 G4LogicalVolume* electronics_logic =
new G4LogicalVolume(electronics_solid,
246 electronics_mat, G4String(
GetName()) +
"_Electronics", 0, 0, 0);
247 VisAtt =
new G4VisAttributes();
249 VisAtt->SetVisibility(
true);
251 electronics_logic->SetVisAttributes(VisAtt);
253 new G4PVPlacement(G4Transform3D::Identity, electronics_logic,
259 "enclosure_thickness") *
262 "enclosure_material");
264 G4VSolid* outer_enclosur_solid =
new G4Box(
265 G4String(
GetName()) +
"_outer_enclosur_solid", enclosure_x * 0.5,
268 G4VSolid* inner_enclosur_solid =
new G4Box(
269 G4String(
GetName()) +
"_inner_enclosur_solid",
270 enclosure_x * 0.5 - enclosure_thickness,
271 enclosure_y * 0.5 - enclosure_thickness,
272 enclosure_z * 0.5 - enclosure_thickness);
273 G4VSolid* enclosure_solid =
new G4SubtractionSolid(
274 G4String(
GetName()) +
"_enclosure_solid",
275 outer_enclosur_solid, inner_enclosur_solid);
276 enclosure_solid =
new G4DisplacedSolid(
277 G4String(
GetName() +
"_enclosure_solid_displaced"), enclosure_solid, 0,
278 G4ThreeVector(box_x_shift, 0, box_z_shift));
280 G4Material* enclosure_mat = G4Material::GetMaterial(enclosure_material);
283 G4LogicalVolume* enclosure_logic =
new G4LogicalVolume(enclosure_solid,
284 enclosure_mat, G4String(
GetName()) +
"_enclosure", 0, 0, 0);
285 VisAtt =
new G4VisAttributes();
287 VisAtt->SetVisibility(
true);
289 enclosure_logic->SetVisAttributes(VisAtt);
291 new G4PVPlacement(G4Transform3D::Identity, enclosure_logic,
297 ostringstream geonode;
316 geonode.str(),
"PHObject");
325 cout <<
"PHG4SpacalPrototypeDetector::Construct::" <<
GetName()
326 <<
" - Print Layer Geometry:" << endl;
333 ostringstream geonode;
340 geonode <<
"CYLINDERGEOM_ABSORBER_" <<
detector_type <<
"_" << 0;
359 cout <<
"PHG4SpacalPrototypeDetector::Construct::" <<
GetName()
360 <<
" - Print Absorber Layer Geometry:" << endl;
367 cout <<
"PHG4SpacalPrototypeDetector::Construct::" <<
GetName()
368 <<
" - Completed. Print G4 Geometry:" << endl;
370 cout <<
"box_x_shift = " << box_x_shift << endl;
371 cout <<
"box_z_shift = " << box_z_shift << endl;
375 std::pair<G4LogicalVolume*, G4Transform3D>
381 G4VSolid* sec_solid =
new G4Tubs(G4String(
GetName() +
string(
"_sec")),
388 sec_solid =
new G4DisplacedSolid(G4String(
GetName() +
"_displaced" +
string(
"_sec")),
390 G4ThreeVector(0, 0, box_z_shift));
392 G4Material* cylinder_mat = G4Material::GetMaterial(
"G4_AIR");
395 G4LogicalVolume* sec_logic =
new G4LogicalVolume(sec_solid, cylinder_mat,
398 G4VisAttributes* VisAtt =
new G4VisAttributes();
399 VisAtt->SetColor(.5, .9, .5, .1);
400 VisAtt->SetVisibility(
402 VisAtt->SetForceSolid(
false);
403 VisAtt->SetForceWireframe(
true);
404 sec_logic->SetVisAttributes(VisAtt);
543 G4PVPlacement* block_phys =
new G4PVPlacement(block_trans, LV_tower,
544 LV_tower->GetName(), sec_logic,
false, g_tower.
id,
552 for (
int ix = 0; ix < g_tower.
NSubtowerX; ix++)
555 for (
int iy = 0; iy < g_tower.
NSubtowerY; iy++)
561 new G4PVPlacement(block_trans, LV_lg, LV_lg->GetName(),
562 sec_logic,
false, g_tower.
id, overlapcheck_block);
568 cout <<
"PHG4SpacalPrototypeDetector::Construct_AzimuthalSeg::" <<
GetName()
570 <<
" unique towers" << endl;
572 return make_pair(sec_logic, G4Transform3D::Identity);
579 G4Tubs* fiber_solid =
new G4Tubs(G4String(
GetName() +
string(
"_fiber") +
id),
582 G4Material* clading_mat = G4Material::GetMaterial(
586 G4LogicalVolume* fiber_logic =
new G4LogicalVolume(fiber_solid, clading_mat,
587 G4String(G4String(
GetName() +
string(
"_fiber") +
id)), 0, 0,
591 G4VisAttributes* VisAtt =
new G4VisAttributes();
595 fiber_logic->SetVisAttributes(VisAtt);
598 G4Tubs* core_solid =
new G4Tubs(
599 G4String(
GetName() +
string(
"_fiber_core") +
id), 0,
605 G4LogicalVolume* core_logic =
new G4LogicalVolume(core_solid, core_mat,
606 G4String(G4String(
GetName() +
string(
"_fiber_core") +
id)), 0, 0,
610 G4VisAttributes* VisAtt =
new G4VisAttributes();
612 VisAtt->SetVisibility(
false);
613 VisAtt->SetForceSolid(
false);
614 core_logic->SetVisAttributes(VisAtt);
618 G4PVPlacement* core_physi =
new G4PVPlacement(0, G4ThreeVector(), core_logic,
619 G4String(G4String(
GetName() +
string(
"_fiber_core") +
id)), fiber_logic,
620 false, 0, overlapcheck_fiber);
630 cout <<
"PHG4SpacalPrototypeDetector::Print::" <<
GetName()
631 <<
" - Print Geometry:" << endl;
640 G4LogicalVolume* LV_tower)
648 typedef map<int, pair<G4Vector3D, G4Vector3D> > fiber_par_map;
649 fiber_par_map fiber_par;
650 G4double min_fiber_length = g_tower.
pDz *
cm * 4;
652 G4Vector3D v_zshift = G4Vector3D(tan(g_tower.
pTheta) * cos(g_tower.
pPhi),
656 for (
int ix = 0; ix < g_tower.
NFiberX; ix++)
659 const double weighted_ix =
static_cast<double>(ix) / (g_tower.
NFiberX - 1.);
667 for (
int iy = 0; iy < g_tower.
NFiberY; iy++)
670 if ((ix + iy) % 2 == 1)
673 const double weighted_iy =
static_cast<double>(iy) / (g_tower.
NFiberY - 1.);
678 const double weighted_pDx12 = weighted_pDx1 * (1 - weighted_iy) + weighted_pDx2 * (weighted_iy) + weighted_pDy1 * tan(g_tower.
pAlp1);
679 const double weighted_pDx34 = weighted_pDx3 * (1 - weighted_iy) + weighted_pDx4 * (weighted_iy) + weighted_pDy1 * tan(g_tower.
pAlp2);
681 G4Vector3D
v1 = G4Vector3D(weighted_pDx12, weighted_pDy1, 0) - v_zshift;
682 G4Vector3D
v2 = G4Vector3D(weighted_pDx34, weighted_pDy2, 0) + v_zshift;
684 G4Vector3D vector_fiber = (v2 -
v1);
686 G4Vector3D center_fiber = (v2 +
v1) / 2;
693 fiber_par[fiber_ID] = make_pair(vector_fiber, center_fiber);
695 const G4double fiber_length = vector_fiber.mag();
697 min_fiber_length =
min(fiber_length, min_fiber_length);
705 const G4double fiber_length = min_fiber_length;
706 vector<G4double> fiber_cut;
709 ss <<
string(
"_Tower") << g_tower.
id;
710 G4LogicalVolume* fiber_logic =
Construct_Fiber(fiber_length, ss.str());
714 const int fiber_ID = val.first;
715 G4Vector3D vector_fiber = val.second.first;
716 G4Vector3D center_fiber = val.second.second;
717 const G4double optimal_fiber_length = vector_fiber.mag();
719 const G4Vector3D
v1 = center_fiber - 0.5 * vector_fiber;
722 assert(optimal_fiber_length - fiber_length >= 0);
723 fiber_cut.push_back(optimal_fiber_length - fiber_length);
725 center_fiber += (fiber_length / optimal_fiber_length - 1) * 0.5 * vector_fiber;
726 vector_fiber *= fiber_length / optimal_fiber_length;
732 <<
"PHG4SpacalPrototypeDetector::Construct_Fibers_SameLengthFiberPerTower::"
733 <<
GetName() <<
" - constructed fiber " << fiber_ID << ss.str()
735 <<
", Length = " << optimal_fiber_length <<
"-"
736 << (optimal_fiber_length - fiber_length) <<
"mm, "
737 <<
"x = " << center_fiber.x() <<
"mm, "
738 <<
"y = " << center_fiber.y() <<
"mm, "
739 <<
"z = " << center_fiber.z() <<
"mm, "
740 <<
"vx = " << vector_fiber.x() <<
"mm, "
741 <<
"vy = " << vector_fiber.y() <<
"mm, "
742 <<
"vz = " << vector_fiber.z() <<
"mm, "
745 const G4double rotation_angle = G4Vector3D(0, 0, 1).angle(vector_fiber);
746 const G4Vector3D rotation_axis =
747 rotation_angle == 0 ? G4Vector3D(1, 0, 0) : G4Vector3D(0, 0, 1).cross(vector_fiber);
749 G4Transform3D fiber_place(
750 G4Translate3D(center_fiber.x(), center_fiber.y(), center_fiber.z()) * G4Rotate3D(rotation_angle, rotation_axis));
757 G4PVPlacement* fiber_physi =
new G4PVPlacement(fiber_place, fiber_logic,
758 G4String(name.str()), LV_tower,
false, fiber_ID,
767 <<
"PHG4SpacalPrototypeDetector::Construct_Fibers_SameLengthFiberPerTower::"
768 <<
GetName() <<
" - constructed tower ID " << g_tower.
id <<
" with "
769 << fiber_count <<
" fibers. Average fiber length cut = "
770 << accumulate(fiber_cut.begin(), fiber_cut.end(), 0.0) / fiber_cut.size() <<
" mm" << endl;
784 cout <<
"PHG4SpacalPrototypeDetector::Construct_Tower::" <<
GetName()
785 <<
" - constructed tower ID " << g_tower.
id
786 <<
" with geometry parameter: ";
790 std::ostringstream sout;
791 sout <<
"_" << g_tower.
id;
792 const G4String sTowerID(sout.str());
796 G4Trap* block_solid =
new G4Trap(
797 G4String(
GetName()) + sTowerID,
806 G4Material* cylinder_mat = G4Material::GetMaterial(
810 G4LogicalVolume* block_logic =
new G4LogicalVolume(block_solid, cylinder_mat,
811 G4String(G4String(
GetName()) +
string(
"_Tower") + sTowerID), 0, 0,
814 G4VisAttributes* VisAtt =
new G4VisAttributes();
816 VisAtt->SetColor(.3, .3, .3, .3);
817 VisAtt->SetVisibility(
820 block_logic->SetVisAttributes(VisAtt);
829 cout <<
"PHG4SpacalPrototypeDetector::Construct_Tower::" <<
GetName()
830 <<
" - constructed tower ID " << g_tower.
id <<
" with " << fiber_count
831 <<
" fibers using Construct_Fibers_SameLengthFiberPerTower" << endl;
839 const int index_x,
const int index_y)
843 std::ostringstream sout;
844 sout <<
"_Lightguide_" << g_tower.
id <<
"_" << index_x <<
"_" << index_y;
845 const G4String sTowerID(sout.str());
851 const double weight_x2 = 1 - (
double) (index_y + 1) / g_tower.
NSubtowerY;
852 const double weight_xcenter = 1 - (
double) (index_y + 0.5) / g_tower.
NSubtowerY;
854 assert(weight_x1 >= 0 and weight_x1 <= 1);
855 assert(weight_x2 >= 0 and weight_x2 <= 1);
856 assert(weight_xcenter >= 0 and weight_xcenter <= 1);
858 const double lg_pDx1 = (g_tower.
pDx1 * weight_x1
859 + g_tower.
pDx2 * (1 - weight_x1)) /
861 const double lg_pDx2 = (g_tower.
pDx1 * weight_x2
862 + g_tower.
pDx2 * (1 - weight_x2)) /
865 const double lg_Alp1 = atan(
868 const double shift_xcenter = (g_tower.
pDx1 * weight_xcenter
869 + g_tower.
pDx2 * (1 - weight_xcenter))
872 const double shift_ycenter = g_tower.
pDy1
876 G4VSolid* block_solid =
new G4Trap(
877 G4String(
GetName()) + sTowerID,
884 lg_pDy1 * cm, lg_pDx1 * cm, lg_pDx2 * cm,
888 block_solid =
new G4DisplacedSolid(G4String(
GetName() +
"_displaced"),
891 tan(g_tower.
pTheta * rad) * cos(g_tower.
pPhi * rad),
892 tan(g_tower.
pTheta * rad) * sin(g_tower.
pPhi * rad),
896 + G4ThreeVector(shift_xcenter * cm, shift_ycenter * cm, 0)
900 G4Material* cylinder_mat = G4Material::GetMaterial(
904 G4LogicalVolume* block_logic =
new G4LogicalVolume(block_solid, cylinder_mat,
905 G4String(G4String(
GetName()) +
string(
"_Tower") + sTowerID), 0, 0,
908 G4VisAttributes* VisAtt =
new G4VisAttributes();
911 VisAtt->SetVisibility(
914 block_logic->SetVisAttributes(VisAtt);