R3BROOT
R3B analysis software
Loading...
Searching...
No Matches
R3BNeulandGeoCreator.cxx
Go to the documentation of this file.
2#include <FairGeoBuilder.h>
3#include <FairGeoInterface.h>
4#include <FairGeoLoader.h>
5#include <FairGeoMedia.h>
6#include <R3BException.h>
7#include <R3BLogger.h>
8#include <R3BNeulandCommon.h>
9#include <TGeoBBox.h>
10#include <TGeoCompositeShape.h>
11#include <TGeoCone.h>
12#include <TGeoManager.h>
13#include <TGeoMatrix.h>
14#include <TGeoShape.h>
15#include <cmath>
16#include <cstdlib>
17#include <fmt/format.h>
18
20{
21 constexpr auto CONE_LENGHT_PADDING = 0.001; // cm
22 constexpr auto BAR_BASE_LENGTH = 125.0; // cm
23 constexpr auto BAR_CONE_LENGTH = 5.; // cm
24
25 const auto BC408_THICKNESS = 2.4; // cm
26 const auto BC408_CONE_RADIUS = 1.2; // cm
27 const auto AL_THICKNESS = 0.02; // cm
28 const auto TAPE_THICKNESS = 0.05; // cm
29
30 constexpr auto DEGREE_90 = 90.;
31 namespace
32 {
33 template <typename T, typename... Args>
34 auto TGeoManagerCreate(Args&&... args) -> T*
35 {
36 return std::make_unique<T>(std::forward<Args>(args)...).release();
37 }
38
39 auto create_cone_displacement(const std::string& name, double rotate_y_degree) -> TGeoCombiTrans*
40 {
41 auto rotation = TGeoRotation{};
42 rotation.RotateY(rotate_y_degree);
43 auto* transition = TGeoManagerCreate<TGeoCombiTrans>(
44 TGeoTranslation{ -(BAR_BASE_LENGTH + BAR_CONE_LENGTH), 0., 0. }, rotation);
45 transition->SetName(name.c_str());
46 transition->RegisterYourself();
47 return transition;
48 }
49
50 auto build_bar_shape(std::string_view name, const BarDimension& bar_dimension) -> TGeoShape*
51 {
52 auto* displace1 = create_cone_displacement("trc1", DEGREE_90);
53 auto* displace2 = create_cone_displacement("trc2", -DEGREE_90);
54
55 auto* main_bar_shape = TGeoManagerCreate<TGeoBBox>(
56 fmt::format("{}Box", name).c_str(), bar_dimension.length, bar_dimension.width, bar_dimension.width);
57 auto* cone_shape = TGeoManagerCreate<TGeoCone>(fmt::format("{}Cone", name).c_str(),
58 bar_dimension.cone_length + CONE_LENGHT_PADDING,
59 0.,
60 bar_dimension.cone_radius,
61 0.,
62 bar_dimension.width * std::sqrt(2.));
63 auto* bar_tail_shape = TGeoManagerCreate<TGeoBBox>(fmt::format("{}ConeBox", name).c_str(),
64 bar_dimension.width,
65 bar_dimension.width,
66 bar_dimension.cone_length);
67 return TGeoManagerCreate<TGeoCompositeShape>(name.data(),
68 fmt::format("{}+(({}*{}):{})+(({}*{}):{})",
69 main_bar_shape->GetName(),
70 bar_tail_shape->GetName(),
71 cone_shape->GetName(),
72 displace1->GetName(),
73 bar_tail_shape->GetName(),
74 cone_shape->GetName(),
75 displace2->GetName())
76 .c_str());
77 }
78
79 } // namespace
80
81 auto Creator::construct_volume(int num_of_planes, FairGeoLoader* geo_loader) -> TGeoVolume*
82 {
83 read_material_from_file(geo_loader);
84 construct_all_material();
85 construct_all_shapes();
86 construct_all_volumes();
87 return build_detector(num_of_planes);
88 }
89
90 auto Creator::build_detector(int num_of_planes) -> TGeoVolume*
91 {
92 auto* neuland = TGeoManagerCreate<TGeoVolumeAssembly>("volNeuland");
93
94 auto total_module_size = num_of_planes * BarsPerPlane;
95 const auto first_plane_front_z = -num_of_planes * BarSize_Z / 2.;
96
97 auto rot_zero = TGeoRotation{};
98 auto rot_90 = TGeoRotation{};
99 rot_90.RotateZ(DEGREE_90);
100
101 for (int module_id{}; module_id < total_module_size; ++module_id)
102 {
103 const auto plane_id = ModuleID2PlaneID(module_id);
104 const auto is_horizontal = IsPlaneIDHorizontal(plane_id);
105 const auto z_pos = PlaneID2ZPos(plane_id) + first_plane_front_z;
106 const auto vertical_displacement = GetBarVerticalDisplacement(module_id + 1);
107 auto* translation_rotation = TGeoManagerCreate<TGeoCombiTrans>();
108 if (is_horizontal)
109 {
110 translation_rotation->SetTranslation(0, vertical_displacement, z_pos);
111 translation_rotation->SetRotation(rot_zero);
112 }
113 else
114 {
115 translation_rotation->SetTranslation(vertical_displacement, 0, z_pos);
116 translation_rotation->SetRotation(rot_90);
117 }
118 neuland->AddNode(bar_, module_id + 1, translation_rotation);
119 }
120
121 return neuland;
122 }
123
124 void Creator::construct_all_volumes()
125 {
126 scintillator_ = build_scintillator();
127 Al_wrapping_ = build_Al_wrapping();
128 tape_wrapping_ = build_tape_wrapping();
129 bar_ = build_bar_volume();
130 }
131
132 void Creator::construct_all_material()
133 {
134 material_BC408_ = build_material("BC408");
135 material_poly_ = build_material("polyethylene");
136 material_Al_ = build_material("aluminium");
137 }
138
139 void Creator::construct_all_shapes()
140 {
141 auto dimension = BarDimension{};
142
143 dimension.length = BAR_BASE_LENGTH;
144 dimension.width = BC408_THICKNESS;
145 dimension.cone_radius = BC408_CONE_RADIUS;
146 dimension.cone_length = BAR_CONE_LENGTH;
147 shape_scintillator_ = build_bar_shape("shapeBC408", dimension);
148
149 dimension.width += AL_THICKNESS;
150 dimension.cone_radius += AL_THICKNESS;
151 auto* shape_Al_solid = build_bar_shape("shapeAlWrappingSolid", dimension);
152 shape_Al_wrapping_ = TGeoManagerCreate<TGeoCompositeShape>(
153 "shapeAlWrapping",
154 fmt::format("{} - {}", shape_Al_solid->GetName(), shape_scintillator_->GetName()).c_str());
155
156 dimension.width += TAPE_THICKNESS;
157 dimension.cone_radius += TAPE_THICKNESS;
158 auto* shape_tape_solid = build_bar_shape("shapeTapeWrappingSolid", dimension);
159 shape_tape_wrapping_ = TGeoManagerCreate<TGeoCompositeShape>(
160 "shapeTapeWrapping",
161 fmt::format("{} - {}", shape_tape_solid->GetName(), shape_Al_solid->GetName()).c_str());
162 }
163
164 auto Creator::build_bar_volume() -> TGeoVolume*
165 {
166 auto* bar = TGeoManagerCreate<TGeoVolumeAssembly>("volPaddle");
167 bar->AddNode(scintillator_, 1);
168 bar->AddNode(Al_wrapping_, 1);
169 bar->AddNode(tape_wrapping_, 1);
170 return bar;
171 }
172
173 auto Creator::build_scintillator() -> TGeoVolume*
174 {
175 auto* scintillator = TGeoManagerCreate<TGeoVolume>("volBC408", shape_scintillator_, material_BC408_);
176 static constexpr auto greyish_blue = 33;
177 static constexpr auto transparency = 30;
178 scintillator->SetLineColor(greyish_blue);
179 scintillator->SetTransparency(transparency);
180 return scintillator;
181 }
182
183 auto Creator::build_Al_wrapping() -> TGeoVolume*
184 {
185 auto* Al_wrapping = TGeoManagerCreate<TGeoVolume>("volAlWrapping", shape_Al_wrapping_, material_Al_);
186 static constexpr auto greyish_silver = 17;
187 Al_wrapping->SetLineColor(greyish_silver); // grey/silver
188 return Al_wrapping;
189 }
190
191 auto Creator::build_tape_wrapping() -> TGeoVolume*
192 {
193 auto* tape_wrapping = TGeoManagerCreate<TGeoVolume>("volTapeWrapping", shape_tape_wrapping_, material_poly_);
194 static constexpr auto black = 1;
195 tape_wrapping->SetLineColor(black); // grey/silver
196 return tape_wrapping;
197 }
198
199 auto Creator::build_material(const std::string& material_name) -> TGeoMedium*
200 {
201 auto* fair_medium = geo_media_->getMedium(material_name.c_str());
202 if (fair_medium == nullptr)
203 {
204 R3BLOG(error, fmt::format("FairGeoMedium {} not found!", material_name));
205 }
206
207 if (geo_builder_ == nullptr)
208 {
209 throw R3B::runtime_error("geo_builder is nullptr!");
210 }
211 geo_builder_->createMedium(fair_medium);
212 if (gGeoManager == nullptr)
213 {
214 throw R3B::runtime_error("gGeoManager is nullptr!");
215 }
216 auto* material = gGeoManager->GetMedium(material_name.c_str());
217 if (material == nullptr)
218 {
219 R3BLOG(error, fmt::format("TGeoMedium {} not found!", material_name));
220 }
221 return material;
222 }
223
224 void Creator::read_material_from_file(FairGeoLoader* geo_loader)
225 {
226 auto* geo_interface = geo_loader->getGeoInterface();
227 const auto working_dir = std::string{ std::getenv("VMCWORKDIR") };
228 if (working_dir.empty())
229 {
230 throw R3B::logic_error("Environment variable \"VMCWORKDIR\" is not defined!");
231 }
232 geo_interface->setMediaFile(fmt::format("{}/geometry/media_r3b.geo", working_dir).c_str());
233 geo_interface->readMedia();
234
235 geo_builder_ = geo_loader->getGeoBuilder();
236 geo_media_ = geo_interface->getMedia();
237 }
238} // namespace R3B::Neuland::Geometry
#define R3BLOG(severity, x)
Definition R3BLogger.h:35
auto construct_volume(int num_of_planes, FairGeoLoader *geo_loader) -> TGeoVolume *
constexpr auto BarsPerPlane
constexpr auto ModuleID2PlaneID(int moduleID) -> int
constexpr auto GetBarVerticalDisplacement(int module_num) -> double
constexpr auto BarSize_Z
constexpr auto IsPlaneIDHorizontal(int plane_id) -> bool
constexpr auto PlaneID2ZPos(int plane_id) -> T