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