File indexing completed on 2025-12-17 09:22:12
0001 #include "PHG4TpcEndCapDetector.h"
0002
0003 #include "PHG4TpcEndCapDisplayAction.h"
0004
0005 #include <phparameter/PHParameters.h>
0006
0007 #include <g4main/PHG4Detector.h>
0008 #include <g4main/PHG4DisplayAction.h> // for PHG4DisplayAction
0009 #include <g4main/PHG4Subsystem.h>
0010
0011 #include <TSystem.h>
0012
0013 #include <Geant4/G4AssemblyVolume.hh>
0014 #include <Geant4/G4Box.hh>
0015 #include <Geant4/G4ExtrudedSolid.hh>
0016 #include <Geant4/G4LogicalVolume.hh>
0017 #include <Geant4/G4Material.hh>
0018 #include <Geant4/G4RotationMatrix.hh>
0019 #include <Geant4/G4String.hh>
0020 #include <Geant4/G4SystemOfUnits.hh>
0021 #include <Geant4/G4ThreeVector.hh>
0022 #include <Geant4/G4Transform3D.hh>
0023 #include <Geant4/G4Tubs.hh>
0024 #include <Geant4/G4TwoVector.hh>
0025 #include <Geant4/G4Types.hh> // for G4double
0026 #include <Geant4/G4VPhysicalVolume.hh>
0027
0028 #include <CLHEP/Vector/RotationZ.h>
0029
0030 #include <algorithm> // for max, copy
0031 #include <cassert>
0032 #include <cmath>
0033 #include <cstdlib> // for exit
0034 #include <format>
0035 #include <iostream>
0036
0037 class G4VSolid;
0038 class PHCompositeNode;
0039
0040
0041 PHG4TpcEndCapDetector::PHG4TpcEndCapDetector(PHG4Subsystem *subsys,
0042 PHCompositeNode *Node,
0043 PHParameters *parameters,
0044 const std::string &dnam)
0045 : PHG4Detector(subsys, Node, dnam)
0046 , m_Params(parameters)
0047 , m_DisplayAction(dynamic_cast<PHG4TpcEndCapDisplayAction *>(subsys->GetDisplayAction()))
0048
0049 {
0050 assert(subsys->GetDisplayAction());
0051 assert(m_DisplayAction);
0052 Verbosity(m_Params->get_int_param("construction_verbosity"));
0053 }
0054
0055 PHG4TpcEndCapDetector::~PHG4TpcEndCapDetector()
0056 {
0057 if (m_EndCapAssembly)
0058 {
0059 if (Verbosity())
0060 {
0061 std::cout << __PRETTY_FUNCTION__ << " delete m_EndCapAssembly" << std::endl;
0062 }
0063
0064 delete m_EndCapAssembly;
0065 }
0066 }
0067
0068
0069 int PHG4TpcEndCapDetector::IsInDetector(G4VPhysicalVolume *volume) const
0070 {
0071 G4LogicalVolume *logvol = volume->GetLogicalVolume();
0072 std::set<G4LogicalVolume *>::const_iterator iter = m_LogicalVolumesSet.find(logvol);
0073 if (iter != m_LogicalVolumesSet.end())
0074 {
0075 return 1;
0076 }
0077 return 0;
0078 }
0079
0080
0081 void PHG4TpcEndCapDetector::ConstructMe(G4LogicalVolume *logicWorld)
0082 {
0083 assert(m_DisplayAction);
0084
0085 assert(m_EndCapAssembly == nullptr);
0086 m_EndCapAssembly = ConstructEndCapAssembly();
0087 assert(m_EndCapAssembly);
0088
0089 G4TranslateZ3D g4vec_front_z(m_Params->get_double_param("envelop_front_surface_z") * cm);
0090
0091 G4RotateY3D rotm_otherside(180 * deg);
0092
0093 G4ThreeVector g4vec_center(m_Params->get_double_param("place_x") * cm,
0094 m_Params->get_double_param("place_y") * cm,
0095 m_Params->get_double_param("place_z") * cm);
0096 G4RotationMatrix rotm_center;
0097 rotm_center.rotateX(m_Params->get_double_param("rot_x") * deg);
0098 rotm_center.rotateY(m_Params->get_double_param("rot_y") * deg);
0099 rotm_center.rotateZ(m_Params->get_double_param("rot_z") * deg);
0100 G4Transform3D transform_center(rotm_center, g4vec_center);
0101
0102 int i = 0;
0103
0104 G4Transform3D transform_side1 = transform_center * g4vec_front_z;
0105 m_EndCapAssembly->MakeImprint(logicWorld, transform_side1, i++, OverlapCheck());
0106
0107 G4Transform3D transform_side2 = transform_center * rotm_otherside * g4vec_front_z;
0108 m_EndCapAssembly->MakeImprint(logicWorld, transform_side2, i++, OverlapCheck());
0109
0110 return;
0111 }
0112
0113 G4AssemblyVolume *PHG4TpcEndCapDetector::ConstructEndCapAssembly()
0114 {
0115 G4AssemblyVolume *assemblyvol = new G4AssemblyVolume();
0116 G4double starting_z(0);
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129 std::vector<double> thickness;
0130 std::vector<std::string> material;
0131 material.emplace_back("G4_Cu");
0132 thickness.push_back(0.0005 * 2. * cm);
0133 material.emplace_back("G4_KAPTON");
0134 thickness.push_back(0.005 * cm);
0135 material.emplace_back("sPHENIX_TPC_Gas");
0136 thickness.push_back(0.2 * cm);
0137 G4Material *temp = GetDetectorMaterial("GEMeffective", false);
0138 if (temp == nullptr)
0139 {
0140 CreateCompositeMaterial("GEMeffective", material, thickness);
0141 }
0142 double totalThickness = 0;
0143 for (double thicknes : thickness)
0144 {
0145 totalThickness += thicknes;
0146 }
0147
0148 const int n_GEM_layers = m_Params->get_int_param("n_GEM_layers");
0149
0150
0151 totalThickness *= n_GEM_layers;
0152 AddLayer(assemblyvol, starting_z, G4String("GEMAllParts"), "GEMeffective", totalThickness, 64);
0153
0154
0155
0156 const int n_PCB_layers(16);
0157
0158 AddLayer(assemblyvol, starting_z, G4String("PCBCu"), "G4_Cu", 0.0035 * cm * n_PCB_layers, 80);
0159
0160 AddLayer(assemblyvol, starting_z, "PCBBase", "FR4", 0.00254 * cm * 7 * n_PCB_layers, 100);
0161
0162 ConstructWagonWheel(assemblyvol, starting_z);
0163 ConstructElectronics(assemblyvol, starting_z);
0164
0165 return assemblyvol;
0166 }
0167
0168 void PHG4TpcEndCapDetector::CreateCompositeMaterial(
0169 const std::string &compositeName,
0170 std::vector<std::string> materialName,
0171 const std::vector<double> &thickness)
0172 {
0173
0174
0175
0176 G4Material *tempmat = GetDetectorMaterial(compositeName, false);
0177
0178 if (tempmat != nullptr)
0179 {
0180 std::cout << __PRETTY_FUNCTION__ << " Fatal Error: composite material " << compositeName << " already exists" << std::endl;
0181 assert(!tempmat);
0182 }
0183
0184
0185 assert(materialName.size() == thickness.size());
0186
0187
0188 double totalArealDensity = 0;
0189 double totalThickness = 0;
0190 for (std::vector<double>::size_type i = 0; i < thickness.size(); i++)
0191 {
0192 tempmat = GetDetectorMaterial(materialName[i]);
0193 if (tempmat == nullptr)
0194 {
0195 std::cout << __PRETTY_FUNCTION__ << " Fatal Error: component material " << materialName[i] << " does not exist." << std::endl;
0196 gSystem->Exit(1);
0197 exit(1);
0198 }
0199 totalArealDensity += tempmat->GetDensity() * thickness[i];
0200 totalThickness += thickness[i];
0201 }
0202
0203
0204 double compositeDensity = totalArealDensity / totalThickness;
0205 G4Material *composite = new G4Material(compositeName, compositeDensity, thickness.size());
0206
0207
0208 for (std::vector<double>::size_type i = 0; i < thickness.size(); i++)
0209 {
0210 tempmat = GetDetectorMaterial(materialName[i]);
0211 composite->AddMaterial(tempmat, thickness[i] * tempmat->GetDensity() / totalArealDensity);
0212 }
0213
0214
0215 return;
0216 }
0217
0218 void PHG4TpcEndCapDetector ::AddLayer(
0219 G4AssemblyVolume *assemblyvol,
0220 G4double &z_start,
0221 const std::string &_name,
0222 const std::string &_material,
0223 G4double _depth,
0224 double _percentage_filled
0225 )
0226 {
0227 z_start += _depth / 2.;
0228 G4ThreeVector g4vec(0, 0, z_start);
0229 z_start += _depth / 2.;
0230
0231 std::string name_base = std::format("{}_Layer_{}", GetName(), _name);
0232
0233 G4VSolid *solid_layer = new G4Tubs(
0234 name_base,
0235 m_Params->get_double_param("envelop_r_min") * cm,
0236 m_Params->get_double_param("envelop_r_max") * cm,
0237 _depth * _percentage_filled / 100. / 2.,
0238 0, CLHEP::twopi);
0239
0240 auto *material = GetDetectorMaterial(_material);
0241 if (material == nullptr)
0242 {
0243 std::cout << __PRETTY_FUNCTION__ << " Fatal Error: missing material " << _material << std::endl;
0244 assert(material);
0245 }
0246
0247 G4LogicalVolume *logical_layer = new G4LogicalVolume(solid_layer, material, name_base);
0248 m_LogicalVolumesSet.insert(logical_layer);
0249
0250 assemblyvol->AddPlacedVolume(logical_layer, g4vec, nullptr);
0251
0252 assert(m_DisplayAction);
0253 m_DisplayAction->AddVolume(logical_layer, _material);
0254
0255 return;
0256 }
0257
0258 void PHG4TpcEndCapDetector::ConstructWagonWheel(G4AssemblyVolume *assmeblyvol,
0259 G4double &z_start)
0260 {
0261 const int n_sectors = m_Params->get_int_param("n_sectors");
0262 assert(n_sectors >= 1);
0263 const int n_radial_modules = m_Params->get_int_param("n_radial_modules");
0264 assert(n_radial_modules >= 1);
0265
0266 const std::string material_name(m_Params->get_string_param("wagon_wheel_material"));
0267 auto *material = GetDetectorMaterial(material_name);
0268 if (material == nullptr)
0269 {
0270 std::cout << __PRETTY_FUNCTION__ << " Fatal Error: missing material " << m_Params->get_string_param("wagon_wheel_material") << std::endl;
0271 assert(material);
0272 }
0273 const G4double wagon_wheel_sector_phi_offset = m_Params->get_double_param("wagon_wheel_sector_phi_offset_degree") * degree;
0274
0275
0276
0277
0278 if (Verbosity())
0279 {
0280 std::cout << __PRETTY_FUNCTION__ << " - wagon_wheel_front_frame z_start = " << z_start << std::endl;
0281 }
0282
0283 const G4double wagon_wheel_front_frame_thickness = m_Params->get_double_param("wagon_wheel_front_frame_thickness") * cm;
0284 const G4double wagon_wheel_front_frame_spoke_width = m_Params->get_double_param("wagon_wheel_front_frame_spoke_width") * cm;
0285
0286 z_start += wagon_wheel_front_frame_thickness / 2.;
0287 G4ThreeVector g4vec_wagon_wheel_front_frame(0, 0, z_start);
0288 z_start += wagon_wheel_front_frame_thickness / 2.;
0289
0290 const G4double wagon_wheel_front_frame_R_inner = m_Params->get_double_param("wagon_wheel_front_frame_R_inner") * cm;
0291 const G4double wagon_wheel_front_frame_R_outer = m_Params->get_double_param("wagon_wheel_front_frame_R_outer") * cm;
0292
0293 for (int ring_id = 0; ring_id <= n_radial_modules; ++ring_id)
0294 {
0295 G4double Rin = wagon_wheel_front_frame_R_inner;
0296 G4double Rout = wagon_wheel_front_frame_R_outer;
0297
0298 if (ring_id > 0)
0299 {
0300 Rin = m_Params->get_double_param(std::format("wagon_wheel_front_frame_R_R{}_outer", ring_id)) *
0301 cm;
0302 }
0303 if (ring_id < n_radial_modules)
0304 {
0305 Rout = m_Params->get_double_param(std::format("wagon_wheel_front_frame_R_R{}_inner", ring_id + 1)) *
0306 cm;
0307 }
0308
0309 std::string name_base = std::format("{}_{}_Ring{}", GetName(), "wagon_wheel_front_frame", ring_id);
0310
0311
0312 G4VSolid *solid_wagon_wheel_front_frame = new G4Tubs(
0313 name_base,
0314 Rin,
0315 Rout,
0316 wagon_wheel_front_frame_thickness / 2.,
0317 0, CLHEP::twopi);
0318
0319 G4LogicalVolume *log_solid_wagon_wheel_front_frame = new G4LogicalVolume(solid_wagon_wheel_front_frame, material, name_base);
0320 m_LogicalVolumesSet.insert(log_solid_wagon_wheel_front_frame);
0321
0322 assmeblyvol->AddPlacedVolume(log_solid_wagon_wheel_front_frame,
0323 g4vec_wagon_wheel_front_frame,
0324 nullptr);
0325 assert(m_DisplayAction);
0326 m_DisplayAction->AddVolume(log_solid_wagon_wheel_front_frame, "wagon_wheel");
0327
0328 }
0329
0330
0331
0332
0333 for (int ring_id = 1; ring_id <= n_radial_modules; ++ring_id)
0334 {
0335 G4double Rout =
0336 m_Params->get_double_param(std::format("wagon_wheel_front_frame_R_R{}_outer", ring_id)) * cm;
0337 G4double Rin =
0338 m_Params->get_double_param(std::format("wagon_wheel_front_frame_R_R{}_inner", ring_id)) * cm;
0339
0340 const G4double reduced_height = std::sqrt(Rout * Rout - wagon_wheel_front_frame_spoke_width / 2 * wagon_wheel_front_frame_spoke_width / 2);
0341
0342 std::vector<G4TwoVector> vertexes;
0343 vertexes.emplace_back(-wagon_wheel_front_frame_spoke_width / 2, Rin);
0344 vertexes.emplace_back(+wagon_wheel_front_frame_spoke_width / 2, Rin);
0345 vertexes.emplace_back(+wagon_wheel_front_frame_spoke_width / 2, reduced_height);
0346 vertexes.emplace_back(-wagon_wheel_front_frame_spoke_width / 2, reduced_height);
0347
0348 G4TwoVector zero(0, 0);
0349
0350 std::string name_base_spoke = std::format("{}_{}_Ring{}_spoke", GetName(), "wagon_wheel_front_frame", ring_id);
0351
0352
0353 G4VSolid *solid_wagon_wheel_front_frame_spoke = new G4ExtrudedSolid(name_base_spoke,
0354 vertexes,
0355 wagon_wheel_front_frame_thickness / 2.,
0356 zero, 1.0,
0357 zero, 1.0);
0358 G4LogicalVolume *log_solid_wagon_wheel_front_frame_spoke = new G4LogicalVolume(solid_wagon_wheel_front_frame_spoke, material, name_base_spoke);
0359 m_LogicalVolumesSet.insert(log_solid_wagon_wheel_front_frame_spoke);
0360
0361 const G4double sector_dphi = CLHEP::twopi / n_sectors;
0362 for (int sector_id = 0; sector_id < n_sectors; ++sector_id)
0363 {
0364 G4Transform3D trans_spoke(CLHEP::HepRotationZ(wagon_wheel_sector_phi_offset + sector_dphi * sector_id), g4vec_wagon_wheel_front_frame);
0365
0366 assmeblyvol->AddPlacedVolume(log_solid_wagon_wheel_front_frame_spoke,
0367 trans_spoke);
0368 assert(m_DisplayAction);
0369 m_DisplayAction->AddVolume(log_solid_wagon_wheel_front_frame_spoke, "wagon_wheel");
0370
0371 }
0372
0373 }
0374
0375
0376
0377
0378 if (Verbosity())
0379 {
0380 std::cout << __PRETTY_FUNCTION__ << " - wagon_wheel_rim_outer z_start = " << z_start << std::endl;
0381 }
0382
0383 {
0384 const G4double wagon_wheel_rim_outer_Rin = m_Params->get_double_param("wagon_wheel_rim_outer_Rin") * cm;
0385 const G4double wagon_wheel_rim_outer_Rout = m_Params->get_double_param("wagon_wheel_rim_outer_Rout") * cm;
0386 const G4double wagon_wheel_rim_outer_thickness = m_Params->get_double_param("wagon_wheel_rim_outer_thickness") * cm;
0387
0388 G4ThreeVector g4vec_wagon_wheel_rim_outer(0, 0, z_start + wagon_wheel_rim_outer_thickness / 2.);
0389
0390 std::string name_base = std::format("{}_wagon_wheel_rim_outer", GetName());
0391
0392
0393 G4VSolid *solid_wagon_wheel = new G4Tubs(
0394 name_base,
0395 wagon_wheel_rim_outer_Rin,
0396 wagon_wheel_rim_outer_Rout,
0397 wagon_wheel_rim_outer_thickness / 2.,
0398 0, CLHEP::twopi);
0399
0400 G4LogicalVolume *log_solid_wagon_wheel = new G4LogicalVolume(solid_wagon_wheel, material, name_base);
0401 m_LogicalVolumesSet.insert(log_solid_wagon_wheel);
0402
0403 assmeblyvol->AddPlacedVolume(log_solid_wagon_wheel,
0404 g4vec_wagon_wheel_rim_outer,
0405 nullptr);
0406 assert(m_DisplayAction);
0407 m_DisplayAction->AddVolume(log_solid_wagon_wheel, "wagon_wheel");
0408
0409 }
0410
0411
0412
0413
0414 {
0415 const G4double wagon_wheel_spoke_width = m_Params->get_double_param("wagon_wheel_spoke_width") * cm;
0416 const G4double wagon_wheel_spoke_height_inner = m_Params->get_double_param("wagon_wheel_spoke_height_inner") * cm;
0417 const G4double wagon_wheel_spoke_height_outer = m_Params->get_double_param("wagon_wheel_spoke_height_outer") * cm;
0418 const G4double wagon_wheel_spoke_R_inner = m_Params->get_double_param("wagon_wheel_spoke_R_inner") * cm;
0419 const G4double wagon_wheel_spoke_R_outer = m_Params->get_double_param("wagon_wheel_spoke_R_outer") * cm;
0420
0421 std::string name_base = std::format("{}_wagon_wheel_spoke", GetName());
0422
0423 std::vector<G4TwoVector> vertexes;
0424 vertexes.emplace_back(0, wagon_wheel_spoke_R_inner);
0425 vertexes.emplace_back(0, wagon_wheel_spoke_R_outer);
0426 vertexes.emplace_back(wagon_wheel_spoke_height_outer, wagon_wheel_spoke_R_outer);
0427 vertexes.emplace_back(wagon_wheel_spoke_height_inner, wagon_wheel_spoke_R_inner);
0428 G4TwoVector zero(0, 0);
0429
0430 G4VSolid *solid_wagon_wheel_spoke = new G4ExtrudedSolid(name_base,
0431 vertexes,
0432 wagon_wheel_spoke_width / 2.,
0433 zero, 1.0,
0434 zero, 1.0);
0435 G4LogicalVolume *log_solid_wagon_wheel_spoke = new G4LogicalVolume(solid_wagon_wheel_spoke, material, name_base);
0436 m_LogicalVolumesSet.insert(log_solid_wagon_wheel_spoke);
0437
0438 G4ThreeVector g4vec_wagon_wheel_spoke(0, 0, z_start + wagon_wheel_spoke_width / 2.);
0439
0440 const G4double sector_dphi = CLHEP::twopi / n_sectors;
0441 for (int sector_id = 0; sector_id < n_sectors; ++sector_id)
0442 {
0443 G4RotateY3D rotm_spoke(-90 * deg);
0444 G4Transform3D trans_spoke(CLHEP::HepRotationZ(wagon_wheel_sector_phi_offset + sector_dphi * sector_id),
0445 g4vec_wagon_wheel_spoke);
0446 G4Transform3D trans_spoke_final = trans_spoke * rotm_spoke;
0447
0448 assmeblyvol->AddPlacedVolume(log_solid_wagon_wheel_spoke,
0449 trans_spoke_final);
0450 assert(m_DisplayAction);
0451 m_DisplayAction->AddVolume(log_solid_wagon_wheel_spoke, "wagon_wheel");
0452
0453 }
0454
0455 }
0456 }
0457
0458 void PHG4TpcEndCapDetector::ConstructElectronics(G4AssemblyVolume *assmeblyvol,
0459 G4double z_start)
0460 {
0461 const int n_sectors = m_Params->get_int_param("n_sectors");
0462 assert(n_sectors >= 1);
0463
0464 const G4double sector_dphi = CLHEP::twopi / n_sectors;
0465
0466 const int n_radial_modules = m_Params->get_int_param("n_radial_modules");
0467 assert(n_radial_modules >= 1);
0468 const G4double wagon_wheel_sector_phi_offset = m_Params->get_double_param("wagon_wheel_sector_phi_offset_degree") * degree;
0469 const G4double wagon_wheel_spoke_width = m_Params->get_double_param("wagon_wheel_spoke_width") * cm;
0470
0471
0472
0473
0474 const G4double electronics_cooling_block_thickness = m_Params->get_double_param("electronics_cooling_block_thickness") * cm;
0475 if (electronics_cooling_block_thickness > 0)
0476 {
0477 if (Verbosity())
0478 {
0479 std::cout << __PRETTY_FUNCTION__ << " - electronics_cooling_block_material z_start = " << z_start << std::endl;
0480 }
0481
0482 const std::string electronics_cooling_block_material_name(m_Params->get_string_param("electronics_cooling_block_material"));
0483 auto *material = GetDetectorMaterial(electronics_cooling_block_material_name);
0484 if (material == nullptr)
0485 {
0486 std::cout << __PRETTY_FUNCTION__ << " Fatal Error: missing material " << m_Params->get_string_param("electronics_cooling_block_material_name") << std::endl;
0487 gSystem->Exit(1);
0488 exit(1);
0489 }
0490
0491 G4ThreeVector g4vec_electronics_cooling_block(0, 0, z_start + electronics_cooling_block_thickness / 2.);
0492
0493 const G4double electronics_cooling_block_R_inner = m_Params->get_double_param("electronics_cooling_block_R_inner") * cm;
0494 const G4double electronics_cooling_block_R_outer = m_Params->get_double_param("electronics_cooling_block_R_outer") * cm;
0495
0496 for (int ring_id = 0; ring_id <= n_radial_modules; ++ring_id)
0497 {
0498 G4double Rin = electronics_cooling_block_R_inner;
0499 G4double Rout = electronics_cooling_block_R_outer;
0500
0501 if (ring_id > 0)
0502 {
0503 Rin = m_Params->get_double_param(std::format("electronics_cooling_block_R_R{}_outer", ring_id)) * cm;
0504 }
0505 if (ring_id < n_radial_modules)
0506 {
0507 Rout = m_Params->get_double_param(std::format("electronics_cooling_block_R_R{}_inner", ring_id + 1)) * cm;
0508 }
0509
0510 std::string name_base = std::format("{}_{}_Ring{}", GetName(), "electronics_cooling_block", ring_id);
0511
0512 const G4double spoke_phi = atan2(wagon_wheel_spoke_width, Rin);
0513
0514
0515
0516 G4VSolid *solid = new G4Tubs(
0517 name_base,
0518 Rin,
0519 Rout,
0520 electronics_cooling_block_thickness / 2.,
0521 spoke_phi, sector_dphi - 2 * spoke_phi);
0522
0523 if (Verbosity())
0524 {
0525 std::cout << __PRETTY_FUNCTION__ << " - electronics_cooling_block " << name_base
0526 << " Rin = " << Rin << " Rout = " << Rout
0527 << " phi = " << spoke_phi << " to " << (sector_dphi - spoke_phi) << std::endl;
0528 }
0529
0530
0531 G4LogicalVolume *log_vol = new G4LogicalVolume(solid, material, name_base);
0532 m_LogicalVolumesSet.insert(log_vol);
0533
0534 for (int sector_id = 0; sector_id < n_sectors; ++sector_id)
0535 {
0536 G4Transform3D trans(
0537 CLHEP::HepRotationZ(wagon_wheel_sector_phi_offset + sector_dphi * sector_id),
0538 g4vec_electronics_cooling_block);
0539
0540 assmeblyvol->AddPlacedVolume(log_vol, trans);
0541 assert(m_DisplayAction);
0542 m_DisplayAction->AddVolume(log_vol, "cooling_block");
0543
0544 }
0545 }
0546 }
0547
0548
0549
0550
0551 const G4double electronics_FEE_depth = m_Params->get_double_param("electronics_FEE_depth") * cm;
0552 const G4double electronics_FEE_Cu_thickness = m_Params->get_double_param("electronics_FEE_Cu_thickness") * cm;
0553 const G4double electronics_FEE_PCB_thickness = m_Params->get_double_param("electronics_FEE_PCB_thickness") * cm;
0554 const G4double electronics_FEE_Al_thickness = m_Params->get_double_param("electronics_FEE_Al_thickness") * cm;
0555 const G4double electronics_assemly_thickness = electronics_FEE_Cu_thickness + electronics_FEE_PCB_thickness + electronics_FEE_Al_thickness;
0556
0557 if (m_Params->get_int_param("electronics_enable") != 0)
0558 {
0559 for (int ring_id = 1; ring_id <= n_radial_modules; ++ring_id)
0560 {
0561 const G4double Rout = m_Params->get_double_param(std::format("electronics_cooling_block_R_R{}_outer", ring_id)) * cm - electronics_assemly_thickness;
0562 const G4double Rin = m_Params->get_double_param(std::format("electronics_cooling_block_R_R{}_inner", ring_id)) * cm + electronics_assemly_thickness;
0563 const int nFEE = m_Params->get_int_param(std::format("electronics_nFEE_R{}", ring_id));
0564
0565
0566 if (nFEE <= 0)
0567 {
0568 std::cout << __PRETTY_FUNCTION__ << " warning : ignore FEE construction for module " << ring_id << " as "
0569 << std::format("electronics_nFEE_R2{}", ring_id) << " = " << nFEE << std::endl;
0570
0571 continue;
0572 }
0573
0574 G4AssemblyVolume *assmeblyvol_electronics = new G4AssemblyVolume();
0575 G4double starting_electronics(0);
0576 std::string name_base = std::format("{}_{}_Ring{}", GetName(), "electronics", ring_id);
0577
0578 if (Verbosity())
0579 {
0580 std::cout << __PRETTY_FUNCTION__ << " - electronics G4_PCB z_start = " << z_start
0581 << " starting_electronics = " << starting_electronics << std::endl;
0582 }
0583 starting_electronics -= electronics_FEE_PCB_thickness / 2.;
0584 G4ThreeVector g4vec_electronics;
0585 g4vec_electronics.set(starting_electronics, (Rout + Rin) * .5, z_start + electronics_FEE_depth / 2.);
0586 starting_electronics -= electronics_FEE_PCB_thickness / 2.;
0587 G4VSolid *solid_electronics = nullptr;
0588 solid_electronics = new G4Box(name_base + "_PCB",
0589 electronics_FEE_PCB_thickness / 2.,
0590 (Rout - Rin) / 2.,
0591 electronics_FEE_depth / 2.);
0592
0593 G4LogicalVolume *log_electronics = nullptr;
0594 log_electronics = new G4LogicalVolume(solid_electronics, GetDetectorMaterial("FR4"), name_base + "_PCB");
0595 m_LogicalVolumesSet.insert(log_electronics);
0596
0597 assmeblyvol_electronics->AddPlacedVolume(log_electronics,
0598 g4vec_electronics, nullptr);
0599 m_DisplayAction->AddVolume(log_electronics, "FR4");
0600 if (Verbosity())
0601 {
0602 std::cout << __PRETTY_FUNCTION__ << " - electronics G4_Cu z_start = " << z_start
0603 << " starting_electronics = " << starting_electronics << std::endl;
0604 }
0605 starting_electronics -= electronics_FEE_Cu_thickness / 2.;
0606 g4vec_electronics.set(starting_electronics, (Rout + Rin) * .5, z_start + electronics_FEE_depth / 2.);
0607 starting_electronics -= electronics_FEE_Cu_thickness / 2.;
0608
0609 solid_electronics = new G4Box(name_base + "_Cu",
0610 electronics_FEE_Cu_thickness / 2.,
0611 (Rout - Rin) / 2.,
0612 electronics_FEE_depth / 2.);
0613
0614 log_electronics = new G4LogicalVolume(solid_electronics, GetDetectorMaterial("G4_Cu"), name_base + "_Cu");
0615 m_LogicalVolumesSet.insert(log_electronics);
0616
0617 assmeblyvol_electronics->AddPlacedVolume(log_electronics,
0618 g4vec_electronics, nullptr);
0619 m_DisplayAction->AddVolume(log_electronics, "Cu");
0620 if (Verbosity())
0621 {
0622 std::cout << __PRETTY_FUNCTION__ << " - electronics Al z_start = " << z_start
0623 << " starting_electronics = " << starting_electronics << std::endl;
0624 }
0625 starting_electronics -= electronics_FEE_Al_thickness / 2.;
0626 g4vec_electronics.set(starting_electronics, (Rout + Rin) * .5, z_start + electronics_FEE_depth / 2.);
0627 starting_electronics -= electronics_FEE_Al_thickness / 2.;
0628
0629 solid_electronics = new G4Box(name_base + "_Al",
0630 electronics_FEE_Al_thickness / 2.,
0631 (Rout - Rin) / 2.,
0632 electronics_FEE_depth / 2.);
0633
0634 log_electronics = new G4LogicalVolume(solid_electronics,
0635 GetDetectorMaterial("G4_Al"),
0636 name_base + "_Al");
0637 m_LogicalVolumesSet.insert(log_electronics);
0638
0639 assmeblyvol_electronics->AddPlacedVolume(log_electronics,
0640 g4vec_electronics, nullptr);
0641 m_DisplayAction->AddVolume(log_electronics, "cooling_block");
0642
0643 for (int sector_id = 0; sector_id < n_sectors; ++sector_id)
0644 {
0645 const G4double sector_phi_shift = wagon_wheel_sector_phi_offset + sector_dphi * sector_id;
0646 const G4double spoke_phi = atan2(wagon_wheel_spoke_width, Rin);
0647 const G4double board_dphi = (sector_dphi - 2 * spoke_phi) / (nFEE + 1);
0648 const G4double board_phi_start = sector_phi_shift + spoke_phi + board_dphi;
0649
0650 for (int board_id = 0; board_id < nFEE; ++board_id)
0651 {
0652 G4Transform3D trans_electronic = G4RotateZ3D(board_phi_start + board_dphi * board_id);
0653
0654 assmeblyvol->AddPlacedAssembly(assmeblyvol_electronics, trans_electronic);
0655 }
0656 }
0657
0658 }
0659 }
0660 }
0661
0662
0663 void PHG4TpcEndCapDetector::Print(const std::string &what) const
0664 {
0665 std::cout << "PHG4TpcEndCap Detector:" << std::endl;
0666 if (what == "ALL" || what == "VOLUME")
0667 {
0668 std::cout << "Version 0.1" << std::endl;
0669 std::cout << "Parameters:" << std::endl;
0670 m_Params->Print();
0671 }
0672 return;
0673 }