Project
Loading...
Searching...
No Matches
FT3Module.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14
16#include <TGeoManager.h>
17#include <TGeoMaterial.h>
18#include <TGeoMedium.h>
19#include <TGeoBBox.h>
20#include <TGeoMatrix.h>
21#include <cmath>
22#include <iostream>
23#include <vector>
24#include <set>
25#include <algorithm>
26
27TGeoMaterial* FT3Module::siliconMat = nullptr;
28TGeoMedium* FT3Module::siliconMed = nullptr;
29
30TGeoMaterial* FT3Module::copperMat = nullptr;
31TGeoMedium* FT3Module::copperMed = nullptr;
32
33TGeoMaterial* FT3Module::kaptonMat = nullptr;
34TGeoMedium* FT3Module::kaptonMed = nullptr;
35
36TGeoMaterial* FT3Module::epoxyMat = nullptr;
37TGeoMedium* FT3Module::epoxyMed = nullptr;
38
39TGeoMaterial* FT3Module::AluminumMat = nullptr;
40TGeoMedium* FT3Module::AluminumMed = nullptr;
41
43{
44
45 if (siliconMat) {
46 return;
47 }
48
49 TGeoManager* gGeoManager = gGeoManager;
50
51 auto* itsH = new TGeoElement("FT3_H", "Hydrogen", 1, 1.00794);
52 auto* itsC = new TGeoElement("FT3_C", "Carbon", 6, 12.0107);
53 auto* itsO = new TGeoElement("FT3_O", "Oxygen", 8, 15.994);
54
55 siliconMat = new TGeoMaterial("FT3_Silicon", 28.0855, 14, 2.33);
56 siliconMed = new TGeoMedium("FT3_Silicon", 1, siliconMat);
57
58 copperMat = new TGeoMaterial("FT3_Copper", 63.546, 29, 8.96);
59 copperMed = new TGeoMedium("FT3_Copper", 2, copperMat);
60
61 kaptonMat = new TGeoMaterial("FT3_Kapton", 13.84, 6.88, 1.346);
62 kaptonMed = new TGeoMedium("FT3_Kapton", 3, kaptonMat);
63
64 // Epoxy: C18 H19 O3
65 auto* itsEpoxy = new TGeoMixture("FT3_Epoxy", 3);
66 itsEpoxy->AddElement(itsC, 18);
67 itsEpoxy->AddElement(itsH, 19);
68 itsEpoxy->AddElement(itsO, 3);
69 itsEpoxy->SetDensity(2.186);
70
71 epoxyMed = new TGeoMedium("FT3_Epoxy", 4, itsEpoxy);
72 epoxyMat = epoxyMed->GetMaterial();
73
74 AluminumMat = new TGeoMaterial("Aluminum", 26.98, 13, 2.7);
75 AluminumMed = new TGeoMedium("Aluminum", 5, AluminumMat);
76}
77
78double calculate_y_circle(double x, double radius)
79{
80 return (x * x < radius * radius) ? std::sqrt(radius * radius - x * x) : 0;
81}
82
83void FT3Module::create_layout(double mZ, int layerNumber, int direction, double Rin, double Rout, double overlap, const std::string& face, const std::string& layout_type, TGeoVolume* motherVolume)
84{
85
86 TGeoManager* gGeoManager = gGeoManager;
87
89
90 // double sensor_width = 2.5;
91 // double sensor_height = 9.6;
92 // double active_width = 2.3;
93 // double active_height = 9.6;
94
95 double sensor_width = 5.0;
96 double sensor_height = 9.6;
97 double inactive_width = 0.2; // per side
98 double active_width = 4.6;
99 double active_height = 9.6;
100
101 double silicon_thickness = 0.01;
102 double copper_thickness = 0.006;
103 double kapton_thickness = 0.03;
104 double epoxy_thickness = 0.0012;
105
106 double carbonFiberThickness = 0.01;
107
108 double foamSpacingThickness = 0.5;
109
110 int dist_offset = 0;
111
112 double x_offset;
113 double y_offset;
114
115 double z_offset = (face == "front") ? -foamSpacingThickness / 2.0 - carbonFiberThickness : foamSpacingThickness / 2.0 + carbonFiberThickness;
116
117 // offset correction
118 if (sensor_height == 3.2 && sensor_width == 2.5) {
119 x_offset = 0.8;
120 y_offset = 1.5;
121 } else if (sensor_height == 19.2 && sensor_width == 5) {
122 x_offset = 0.7;
123 y_offset = 9;
124
125 } else {
126 x_offset = sensor_width / 2;
127 y_offset = sensor_height / 2;
128 }
129
130 double x_condition_min = 0;
131 double x_condition_max = 0;
132 double offset_Rin_lower = 0;
133 double offset_Rin_upper = 0;
134 bool adjust_bottom_y_pos = false;
135 bool adjust_bottom_y_neg = false;
136 double x_adjust_bottom_y_pos = 0;
137 double bottom_y_pos_value = 0;
138 double bottom_y_neg_value = 0;
139
140 if (Rin == 7 && sensor_height == 9.6 && sensor_width == 5) {
141 x_condition_min = -Rin - 2;
142 x_condition_max = Rin;
143 adjust_bottom_y_pos = true;
144 adjust_bottom_y_neg = true;
145 x_adjust_bottom_y_pos = 3.5;
146 bottom_y_pos_value = 3.5;
147 bottom_y_neg_value = -3.5;
148
149 dist_offset = 2;
150
151 } else if (Rin == 5 && sensor_height == 9.6 && sensor_width == 5) {
152 x_condition_min = -Rin - 6;
153 x_condition_max = Rin;
154 adjust_bottom_y_pos = true;
155 adjust_bottom_y_neg = true;
156 x_adjust_bottom_y_pos = 3.5;
157 bottom_y_pos_value = 3.5;
158 bottom_y_neg_value = -3.5;
159 } else if ((Rin == 5 || Rin == 7) && sensor_height == 19.2) {
160 x_condition_min = -Rin - 3;
161 x_condition_max = Rin - 0.2;
162 dist_offset = 2;
163 adjust_bottom_y_pos = false;
164 adjust_bottom_y_neg = false;
165 } else if (Rin == 5 && sensor_height == 3.2) {
166 x_condition_min = -(Rin + 2.6);
167 x_condition_max = Rin + 1.5;
168 adjust_bottom_y_pos = true;
169 adjust_bottom_y_neg = true;
170 x_adjust_bottom_y_pos = 3.5;
171 bottom_y_pos_value = 3.5;
172 bottom_y_neg_value = -3.5;
173 } else if (Rin == 7 && sensor_height == 3.2) {
174 x_condition_min = -Rin - 1;
175 x_condition_max = Rin - 0.2;
176 adjust_bottom_y_pos = true;
177 adjust_bottom_y_neg = true;
178 x_adjust_bottom_y_pos = 3.5;
179 bottom_y_pos_value = 3.5;
180 bottom_y_neg_value = -3.5;
181 } else if (Rin == 5 && sensor_height == 9.6 && sensor_width == 2.5) {
182 x_condition_min = -(Rin + 2.6);
183 x_condition_max = Rin;
184 adjust_bottom_y_pos = true;
185 adjust_bottom_y_neg = true;
186 x_adjust_bottom_y_pos = 3.5;
187 bottom_y_pos_value = 3.5;
188 bottom_y_neg_value = -3.5;
189 } else if (Rin == 7 && sensor_height == 9.6 && sensor_width == 2.5) {
190 x_condition_min = -Rin - 2.6;
191 x_condition_max = Rin + 1;
192 dist_offset = 2;
193 adjust_bottom_y_pos = true;
194 adjust_bottom_y_neg = true;
195 x_adjust_bottom_y_pos = 5.5;
196 bottom_y_pos_value = 3.5;
197 bottom_y_neg_value = -3.5;
198 } else {
199 std::cout << "Different config - to determine offsets needed." << std::endl;
200 x_condition_min = -Rin;
201 x_condition_max = Rin;
202 adjust_bottom_y_pos = false;
203 adjust_bottom_y_neg = false;
204 }
205
206 double Rin_offset = (sensor_height == 19.2) ? 1 : 0;
207 double Rout_offset = (sensor_height == 19.2) ? 1 : 0;
208
209 offset_Rin_lower = Rin - Rin_offset;
210 offset_Rin_upper = Rout + Rout_offset;
211
212 std::set<std::pair<double, double>> placed_sensors;
213 int sensor_count = 0;
214
215 int placementCounter = 0;
216 bool justSkipped = false;
217
218 std::vector<double> X_positions;
219 std::vector<int> justSkipped1;
220
221 if (sensor_width == 2.5) {
222 // logic for placement - x positions with complete overlap
223 if (face == "front") {
224 X_positions = {-63.4, -60.9, -54.2, -51.7, -45.0, -42.5, -35.8, -33.3, -26.6, -24.1, -17.4, -14.9,
225 -8.2, -5.7, 1.0, 3.5, 10.2, 12.7, 19.4, 21.9, 28.6, 31.1, 37.8, 40.3, 47.0, 49.5,
226 56.2, 58.7, 65.4};
227 justSkipped1 = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1};
228 } else if (face == "back") {
229 X_positions = {-65.5, -58.8, -56.3, -49.6, -47.1, -40.4, -37.9, -31.2, -28.7, -22.0, -19.5, -12.8,
230 -10.3, -3.6, -1.1, 5.6, 8.1, 14.8, 17.3, 24.0, 26.5, 33.2, 35.7, 42.4, 44.9,
231 51.6, 54.1, 60.8, 63.3};
232 justSkipped1 = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0};
233 }
234 } else {
235 // filling for sensors with 2x width, each row skipped
236 if (face == "front") {
237 X_positions = {-63.4, -54.2, -45, -35.8, -26.6, -17.4, -8.2, 1., 10.2, 19.4, 28.6, 37.8, 47., 56.2, 65.4};
238 justSkipped1 = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
239 } else if (face == "back") {
240 X_positions = {-58.8, -49.6, -40.4, -31.2, -22, -12.8, -3.6, 5.6, 14.8, 24, 33.2, 42.4, 51.6, 60.8};
241 justSkipped1 = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
242 }
243 }
244
245 if (layout_type == "rectangular") {
246
247 double x_start = -Rout;
248 double x_end = Rout;
249
250 std::vector<double> x_positions;
251 for (double x = x_start; x <= x_end; x += sensor_width) {
252 x_positions.push_back(x);
253 }
254
255 int rowCounter = 0;
256 const int rowsToAlternate = 2;
257
258 for (size_t i = 0; i < X_positions.size(); ++i) {
259
260 double x = X_positions[i];
261 bool justSkippedValue = justSkipped1[i];
262
263 std::vector<double> y_positions_positive;
264 std::vector<double> y_positions_negative;
265
266 for (double y = -Rout - Rin_offset; y <= Rout + Rin_offset; y += sensor_height) {
267 std::vector<std::pair<double, double>> corners = {
268 {x, y},
269 {x + sensor_width, y},
270 {x, y + sensor_height},
271 {x + sensor_width, y + sensor_height}};
272
273 bool within_bounds = std::all_of(corners.begin(), corners.end(), [&](const std::pair<double, double>& corner) {
274 double cx = corner.first;
275 double cy = corner.second;
276 return (offset_Rin_lower <= std::sqrt(cx * cx + cy * cy) && std::sqrt(cx * cx + cy * cy) <= offset_Rin_upper);
277 });
278
279 if (within_bounds) {
280 if (y >= 0) {
281 y_positions_positive.push_back(y);
282 } else {
283 y_positions_negative.push_back(y);
284 }
285 }
286 }
287
288 // adjust y positions near inner circle for positive y
289 if (x_condition_min <= x && x <= x_condition_max && !y_positions_positive.empty()) {
290 double first_y_pos = y_positions_positive.front();
291 double last_y_pos = y_positions_positive.back() - sensor_height;
292 double top_y_pos = std::min(calculate_y_circle(x, Rout), calculate_y_circle(x + sensor_width, Rout));
293 double bottom_y_pos = std::max(calculate_y_circle(x, Rin), calculate_y_circle(x + sensor_width, Rin));
294 double top_distance_pos = top_y_pos - last_y_pos;
295
296 if (adjust_bottom_y_pos && x > x_adjust_bottom_y_pos) {
297 bottom_y_pos = bottom_y_pos_value;
298 }
299
300 double bottom_distance_pos = first_y_pos - bottom_y_pos;
301
302 if (std::abs(top_distance_pos + bottom_distance_pos) >= sensor_height) {
303 for (auto& y : y_positions_positive) {
304 y -= bottom_distance_pos - 0.2;
305 }
306 y_positions_positive.push_back(y_positions_positive.back() + sensor_height);
307 }
308 }
309
310 // adjust y positions near inner circle for negative y
311 if (x_condition_min <= x && x <= x_condition_max && !y_positions_negative.empty()) {
312 double first_y_neg = y_positions_negative.front();
313 double last_y_neg = y_positions_negative.back() + sensor_height;
314 double top_y_neg = -std::min(calculate_y_circle(x, Rout), calculate_y_circle(x + sensor_width, Rout));
315 double bottom_y_neg = -std::max(calculate_y_circle(x, Rin), calculate_y_circle(x + sensor_width, Rin));
316 double top_distance_neg = -(top_y_neg - first_y_neg);
317
318 if (adjust_bottom_y_neg && x > x_adjust_bottom_y_pos) {
319 bottom_y_neg = bottom_y_neg_value;
320 }
321
322 double bottom_distance_neg = -(last_y_neg - bottom_y_neg);
323
324 top_distance_neg = std::abs(top_distance_neg);
325 bottom_distance_neg = std::abs(bottom_distance_neg);
326 std::sort(y_positions_negative.begin(), y_positions_negative.end());
327
328 if (std::abs(top_distance_neg + bottom_distance_neg) >= sensor_height) {
329 if (sensor_height == 19.2) {
330 for (auto& y : y_positions_negative) {
331 y -= bottom_distance_neg;
332 }
333 } else {
334 for (auto& y : y_positions_negative) {
335 y += bottom_distance_neg - 0.2;
336 }
337 }
338 y_positions_negative.push_back(y_positions_negative.front() - sensor_height);
339 }
340 }
341
342 // adjust positions for the rest of the disk
343 if ((x < x_condition_min || x > x_condition_max) && !y_positions_negative.empty() && !y_positions_positive.empty()) {
344 double first_y_neg = y_positions_negative.front();
345 double last_y_pos = y_positions_positive.back() + sensor_height;
346 double top_y_pos = std::min(calculate_y_circle(x, Rout), calculate_y_circle(x + sensor_width, Rout));
347 double bottom_y_pos = -top_y_pos;
348
349 double top_distance_pos = std::abs(top_y_pos - last_y_pos);
350 double bottom_distance_pos = std::abs(first_y_neg - bottom_y_pos);
351
352 if (top_distance_pos + bottom_distance_pos >= sensor_height) {
353 for (auto& y : y_positions_positive) {
354 y += top_distance_pos - 0.2;
355 }
356 for (auto& y : y_positions_negative) {
357 y += top_distance_pos - 0.2;
358 }
359 double new_y = y_positions_negative.front() - sensor_height;
360
361 if (static_cast<int>(new_y) > static_cast<int>(bottom_y_pos)) {
362 y_positions_negative.push_back(new_y);
363 }
364 }
365
366 // Make symmetric adjustments
367 std::sort(y_positions_negative.begin(), y_positions_negative.end());
368 std::sort(y_positions_positive.begin(), y_positions_positive.end());
369
370 double first_y_pos = y_positions_negative.front();
371
372 last_y_pos = y_positions_positive.back() + sensor_height;
373
374 top_y_pos = std::min(calculate_y_circle(x, Rout), calculate_y_circle(x + sensor_width, Rout));
375 bottom_y_pos = -top_y_pos;
376 top_distance_pos = std::abs(top_y_pos - last_y_pos);
377 bottom_distance_pos = std::abs(first_y_pos - bottom_y_pos);
378
379 double Lb = (bottom_distance_pos + top_distance_pos) / 2;
380
381 if (top_distance_pos < Lb) {
382 double shift = Lb - top_distance_pos;
383 for (auto& y : y_positions_negative) {
384 y -= shift;
385 }
386 for (auto& y : y_positions_positive) {
387 y -= shift;
388 }
389 } else if (top_distance_pos > Lb) {
390 double shift = top_distance_pos - Lb;
391 for (auto& y : y_positions_negative) {
392 y += shift;
393 }
394 for (auto& y : y_positions_positive) {
395 y += shift;
396 }
397 }
398 }
399
400 std::vector<double> y_positions = y_positions_positive;
401 y_positions.insert(y_positions.end(), y_positions_negative.begin(), y_positions_negative.end());
402
403 for (double y : y_positions) {
404
405 int SiColor;
406 double R_material_threshold = 0;
407
408 if (placed_sensors.find({x, y}) == placed_sensors.end()) {
409 placed_sensors.insert({x, y});
410 TGeoVolume* sensor;
411
412 double inactive_width = (sensor_width - active_width) / 2;
413 double left_inactive_x_shift;
414 double right_inactive_x_shift;
415 double active_x_shift_sensor;
416
417 if (face == "front") {
418
419 double active_x_shift, inactive_x_shift;
420
421 if (justSkippedValue) {
422 active_x_shift = x + inactive_width / 2;
423 active_x_shift_sensor = active_x_shift + inactive_width;
424
425 inactive_x_shift = x - active_width / 2 + inactive_width / 2;
426 } else {
427 active_x_shift = x - inactive_width / 2;
428 active_x_shift_sensor = active_x_shift - inactive_width;
429
430 inactive_x_shift = x + active_width / 2 - inactive_width / 2;
431 }
432
433 double inactive_x_shift_left, inactive_x_shift_right;
434
435 if (sensor_width == 5.0) {
436
437 inactive_x_shift_left = x - sensor_width / 2 + inactive_width;
438 inactive_x_shift_right = x + sensor_width / 2;
439 }
440
441 std::vector<std::pair<double, double>> corners_shifted = {
442 {x, y},
443 {x + sensor_width, y},
444 {x, y + sensor_height},
445 {x + sensor_width, y + sensor_height}};
446
447 bool within_bounds = true;
448 for (const auto& corner : corners_shifted) {
449 double cx = corner.first;
450 double cy = corner.second;
451 double dist = std::sqrt(cx * cx + cy * cy);
452
453 if (Rin > dist || dist >= Rout) {
454 within_bounds = false;
455 break;
456 }
457 }
458
459 if (within_bounds) {
460
461 double r_squared = (x + x_offset) * (x + x_offset) + (y + y_offset) * (y + y_offset);
462
463 if (r_squared < R_material_threshold * R_material_threshold) {
464 silicon_thickness = 0.005;
465 copper_thickness = 0.00475;
466 kapton_thickness = 0.03;
467 epoxy_thickness = 0.0012;
468
469 SiColor = kOrange;
470 } else {
471 silicon_thickness = 0.01;
472 copper_thickness = 0.006;
473 kapton_thickness = 0.03;
474 epoxy_thickness = 0.0012;
475
476 SiColor = kGreen;
477 }
478
479 if (sensor_width == 2.5) {
480 // silicon
481 std::string sensor_name = "FT3sensor_front_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
482 sensor = gGeoManager->MakeBox(sensor_name.c_str(), siliconMed, active_width / 2, active_height / 2, silicon_thickness / 2);
483 sensor->SetLineColor(SiColor);
484 sensor->SetFillColorAlpha(SiColor, 0.4);
485 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(active_x_shift_sensor + x_offset, y + y_offset, mZ + z_offset - epoxy_thickness - kapton_thickness - copper_thickness - epoxy_thickness - silicon_thickness / 2));
486
487 std::string inactive_name = "FT3inactive_front_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
488 sensor = gGeoManager->MakeBox(inactive_name.c_str(), siliconMed, (sensor_width - active_width) / 2, sensor_height / 2, silicon_thickness / 2);
489 sensor->SetLineColor(kRed);
490 sensor->SetFillColorAlpha(kRed, 1.0);
491 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(x_offset + inactive_x_shift, y + y_offset, mZ + z_offset - epoxy_thickness - kapton_thickness - copper_thickness - epoxy_thickness - silicon_thickness / 2));
492
493 } else {
494
495 std::string sensor_name = "FT3sensor_front_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
496 sensor = gGeoManager->MakeBox(sensor_name.c_str(), siliconMed, active_width / 2, sensor_height / 2, silicon_thickness / 2);
497 sensor->SetLineColor(SiColor);
498 sensor->SetFillColorAlpha(SiColor, 0.4);
499 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(x_offset + x + inactive_width / 2, y + y_offset, mZ + z_offset - epoxy_thickness - kapton_thickness - copper_thickness - epoxy_thickness - silicon_thickness / 2));
500
501 std::string inactive_name_left = "FT3inactive_left_front_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
502 sensor = gGeoManager->MakeBox(inactive_name_left.c_str(), siliconMed, inactive_width / 2, sensor_height / 2, silicon_thickness / 2);
503 sensor->SetLineColor(kRed);
504 sensor->SetFillColorAlpha(kRed, 1.0);
505 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(x_offset + inactive_x_shift_left, y + y_offset, mZ + z_offset - epoxy_thickness - kapton_thickness - copper_thickness - epoxy_thickness - silicon_thickness / 2));
506
507 std::string inactive_name_right = "FT3inactive_right_front_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
508 sensor = gGeoManager->MakeBox(inactive_name_right.c_str(), siliconMed, inactive_width / 2, sensor_height / 2, silicon_thickness / 2);
509 sensor->SetLineColor(kRed);
510 sensor->SetFillColorAlpha(kRed, 1.0);
511 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(x_offset + inactive_x_shift_right, y + y_offset, mZ + z_offset - epoxy_thickness - kapton_thickness - copper_thickness - epoxy_thickness - silicon_thickness / 2));
512 }
513
514 // silicon-to-FPC epoxy glue
515 std::string glue_up_name = "FT3glue_up_front_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
516 sensor = gGeoManager->MakeBox(glue_up_name.c_str(), epoxyMed, sensor_width / 2, sensor_height / 2, epoxy_thickness / 2);
517 sensor->SetLineColor(kBlue);
518 sensor->SetFillColorAlpha(kBlue, 1.0);
519 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(x_offset + active_x_shift, y + y_offset, mZ + z_offset - epoxy_thickness - kapton_thickness - copper_thickness - epoxy_thickness / 2));
520
521 if (r_squared < R_material_threshold * R_material_threshold) {
522 std::string alu_name = "FT3aluminum_front_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
523 sensor = gGeoManager->MakeBox(alu_name.c_str(), AluminumMed, sensor_width / 2, sensor_height / 2, copper_thickness / 2);
524 sensor->SetLineColor(kBlack);
525 sensor->SetFillColorAlpha(kBlack, 0.4);
526 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(active_x_shift + x_offset, y + y_offset, mZ + z_offset - epoxy_thickness - kapton_thickness - copper_thickness / 2));
527
528 } else {
529 std::string copper_name = "FT3copper_front_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
530 sensor = gGeoManager->MakeBox(copper_name.c_str(), copperMed, sensor_width / 2, sensor_height / 2, copper_thickness / 2);
531 sensor->SetLineColor(kBlack);
532 sensor->SetFillColorAlpha(kBlack, 0.4);
533 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(active_x_shift + x_offset, y + y_offset, mZ + z_offset - epoxy_thickness - kapton_thickness - copper_thickness / 2));
534 }
535
536 // kapton
537 std::string fpc_name = "FT3fpc_front_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
538 sensor = gGeoManager->MakeBox(fpc_name.c_str(), kaptonMed, sensor_width / 2, sensor_height / 2, kapton_thickness / 2);
539 sensor->SetLineColor(kGreen);
540 sensor->SetFillColorAlpha(kGreen, 0.4);
541 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(active_x_shift + x_offset, y + y_offset, mZ + z_offset - epoxy_thickness - kapton_thickness / 2));
542
543 // FPC-to-support epoxy glue
544 std::string glue_down_name = "FT3glue_down_front_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
545 sensor = gGeoManager->MakeBox(glue_down_name.c_str(), epoxyMed, sensor_width / 2, sensor_height / 2, epoxy_thickness / 2);
546 sensor->SetLineColor(kBlue);
547 sensor->SetFillColorAlpha(kBlue, 1.0);
548 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(x_offset + active_x_shift, y + y_offset, mZ + z_offset - epoxy_thickness / 2));
549 }
550 } else {
551 double x_shifted = x;
552 double inactive_x_shift, active_x_shift;
553 double active_x_shift_sensor;
554
555 if (justSkippedValue) {
556 active_x_shift = x + inactive_width / 2;
557 active_x_shift_sensor = active_x_shift + inactive_width;
558
559 inactive_x_shift = x - active_width / 2 + inactive_width / 2;
560 } else {
561 active_x_shift = x - inactive_width / 2;
562 active_x_shift_sensor = active_x_shift - inactive_width;
563
564 inactive_x_shift = x + active_width / 2 - inactive_width / 2;
565 }
566
567 double inactive_x_shift_left, inactive_x_shift_right;
568
569 if (sensor_width == 5.0) {
570
571 inactive_x_shift_left = x - sensor_width / 2 + inactive_width;
572 inactive_x_shift_right = x + sensor_width / 2;
573 }
574
575 std::vector<std::pair<double, double>> corners_shifted = {
576 {x_shifted, y},
577 {x_shifted + sensor_width, y},
578 {x_shifted, y + sensor_height},
579 {x_shifted + sensor_width, y + sensor_height}};
580
581 bool within_bounds = true;
582 for (const auto& corner : corners_shifted) {
583 double cx = corner.first;
584 double cy = corner.second;
585 double dist = std::sqrt(cx * cx + cy * cy);
586
587 if (Rin > dist + dist_offset || dist >= Rout) {
588 within_bounds = false;
589 break;
590 }
591 }
592
593 if (within_bounds) {
594
595 double r_squared = (x + x_offset) * (x + x_offset) + (y + y_offset) * (y + y_offset);
596
597 if (r_squared < R_material_threshold * R_material_threshold) {
598 silicon_thickness = 0.005;
599 copper_thickness = 0.00475; // thinner -> + replaced by alu
600 kapton_thickness = 0.03;
601 epoxy_thickness = 0.0006;
602
603 SiColor = kOrange;
604 } else {
605 silicon_thickness = 0.01;
606 copper_thickness = 0.006;
607 kapton_thickness = 0.03;
608 epoxy_thickness = 0.0012;
609
610 SiColor = kGreen;
611 }
612
613 // FPC-to-support epoxy glue
614 std::string glue_down_name = "FT3glue_down_back_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
615 sensor = gGeoManager->MakeBox(glue_down_name.c_str(), epoxyMed, sensor_width / 2, sensor_height / 2, epoxy_thickness / 2);
616 sensor->SetLineColor(kBlue);
617 sensor->SetFillColorAlpha(kBlue, 1.0);
618 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(x_offset + active_x_shift, y + y_offset, mZ + z_offset + epoxy_thickness / 2));
619
620 // Kapton
621 std::string fpc_name = "FT3fpc_back_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
622 sensor = gGeoManager->MakeBox(fpc_name.c_str(), kaptonMed, sensor_width / 2, sensor_height / 2, kapton_thickness / 2);
623 sensor->SetLineColor(kGreen);
624 sensor->SetFillColorAlpha(kGreen, 0.4);
625 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(active_x_shift + x_offset, y + y_offset, mZ + z_offset + epoxy_thickness + kapton_thickness / 2));
626
627 if (r_squared < R_material_threshold * R_material_threshold) {
628 // replace copper with alu
629 std::string alu_name = "FT3aluminum_back_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
630 sensor = gGeoManager->MakeBox(alu_name.c_str(), AluminumMed, sensor_width / 2, sensor_height / 2, copper_thickness / 2);
631 sensor->SetLineColor(kBlack);
632 sensor->SetFillColorAlpha(kBlack, 0.4);
633 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(active_x_shift + x_offset, y + y_offset, mZ + z_offset + epoxy_thickness + kapton_thickness + copper_thickness / 2));
634
635 } else {
636 std::string copper_name = "FT3copper_back_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
637 sensor = gGeoManager->MakeBox(copper_name.c_str(), copperMed, sensor_width / 2, sensor_height / 2, copper_thickness / 2);
638 sensor->SetLineColor(kBlack);
639 sensor->SetFillColorAlpha(kBlack, 0.4);
640 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(active_x_shift + x_offset, y + y_offset, mZ + z_offset + epoxy_thickness + kapton_thickness + copper_thickness / 2));
641 }
642
643 // silicon-to-FPC epoxy glue
644 std::string glue_up_name = "FT3glue_up_back_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
645 sensor = gGeoManager->MakeBox(glue_up_name.c_str(), epoxyMed, sensor_width / 2, sensor_height / 2, epoxy_thickness / 2);
646 sensor->SetLineColor(kBlue);
647 sensor->SetFillColorAlpha(kBlue, 1.0);
648 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(x_offset + active_x_shift, y + y_offset, mZ + z_offset + epoxy_thickness + kapton_thickness + copper_thickness + epoxy_thickness / 2));
649
650 if (sensor_width == 2.5) {
651
652 std::string sensor_name = "FT3sensor_back_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
653 sensor = gGeoManager->MakeBox(sensor_name.c_str(), siliconMed, active_width / 2, active_height / 2, silicon_thickness / 2);
654 sensor->SetLineColor(SiColor);
655 sensor->SetFillColorAlpha(SiColor, 0.4);
656 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(active_x_shift_sensor + x_offset, y + y_offset, mZ + z_offset + epoxy_thickness + kapton_thickness + copper_thickness + epoxy_thickness + silicon_thickness / 2));
657
658 std::string inactive_name = "FT3inactive_back_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
659 sensor = gGeoManager->MakeBox(inactive_name.c_str(), siliconMed, (sensor_width - active_width) / 2, sensor_height / 2, silicon_thickness / 2);
660 sensor->SetLineColor(kRed);
661 sensor->SetFillColorAlpha(kRed, 1.0);
662 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(x_offset + inactive_x_shift, y + y_offset, mZ + z_offset + epoxy_thickness + kapton_thickness + copper_thickness + epoxy_thickness + silicon_thickness / 2));
663
664 } else {
665 // active (4.6 cm centered)
666 std::string sensor_name = "FT3sensor_back_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
667 sensor = gGeoManager->MakeBox(sensor_name.c_str(), siliconMed, active_width / 2, sensor_height / 2, silicon_thickness / 2);
668 sensor->SetLineColor(SiColor);
669 sensor->SetFillColorAlpha(SiColor, 0.4);
670 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(x_offset + x_shifted + inactive_width / 2, y + y_offset, mZ + z_offset + epoxy_thickness + kapton_thickness + copper_thickness + epoxy_thickness + silicon_thickness / 2));
671
672 // left inactive strip
673 std::string inactive_name_left = "FT3inactive_left_back_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
674 sensor = gGeoManager->MakeBox(inactive_name_left.c_str(), siliconMed, inactive_width / 2, sensor_height / 2, silicon_thickness / 2);
675 sensor->SetLineColor(kRed);
676 sensor->SetFillColorAlpha(kRed, 1.0);
677 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(x_offset + inactive_x_shift_left, y + y_offset, mZ + z_offset + epoxy_thickness + kapton_thickness + copper_thickness + epoxy_thickness + silicon_thickness / 2));
678
679 // right inactive strip
680 std::string inactive_name_right = "FT3inactive_right_back_" + std::to_string(layerNumber) + "_" + std::to_string(direction) + "_" + std::to_string(sensor_count);
681 sensor = gGeoManager->MakeBox(inactive_name_right.c_str(), siliconMed, inactive_width / 2, sensor_height / 2, silicon_thickness / 2);
682 sensor->SetLineColor(kRed);
683 sensor->SetFillColorAlpha(kRed, 1.0);
684 motherVolume->AddNode(sensor, sensor_count++, new TGeoTranslation(x_offset + inactive_x_shift_right, y + y_offset, mZ + z_offset + epoxy_thickness + kapton_thickness + copper_thickness + epoxy_thickness + silicon_thickness / 2));
685 }
686 }
687 }
688 }
689 }
690
691 rowCounter++;
692 }
693 }
694}
695
696void FT3Module::createModule(double mZ, int layerNumber, int direction, double Rin, double Rout, double overlap, const std::string& face, const std::string& layout_type, TGeoVolume* motherVolume)
697{
698 create_layout(mZ, layerNumber, direction, Rin, Rout, overlap, face, layout_type, motherVolume);
699}
double calculate_y_circle(double x, double radius)
Definition FT3Module.cxx:78
Definition of the FT3Module class.
int32_t i
static TGeoMedium * epoxyMed
Definition FT3Module.h:33
static TGeoMaterial * epoxyMat
Definition FT3Module.h:32
static TGeoMedium * siliconMed
Definition FT3Module.h:27
static void createModule(double mZ, int layerNumber, int direction, double Rin, double Rout, double overlap, const std::string &face, const std::string &layout_type, TGeoVolume *motherVolume)
static TGeoMedium * copperMed
Definition FT3Module.h:29
static TGeoMaterial * kaptonMat
Definition FT3Module.h:30
static TGeoMaterial * copperMat
Definition FT3Module.h:28
static TGeoMaterial * siliconMat
Definition FT3Module.h:26
static TGeoMedium * AluminumMed
Definition FT3Module.h:35
static TGeoMedium * kaptonMed
Definition FT3Module.h:31
static TGeoMaterial * AluminumMat
Definition FT3Module.h:34
static void initialize_materials()
Definition FT3Module.cxx:42
GLint GLenum GLint x
Definition glcorearb.h:403
GLenum GLuint GLint GLenum face
Definition glcorearb.h:3184
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52