13 #include <phparameter/PHParameters.h>
22 #include <Geant4/G4LogicalVolume.hh>
23 #include <Geant4/G4Material.hh>
24 #include <Geant4/G4PVPlacement.hh>
25 #include <Geant4/G4String.hh>
26 #include <Geant4/G4SystemOfUnits.hh>
27 #include <Geant4/G4ThreeVector.hh>
28 #include <Geant4/G4Tubs.hh>
29 #include <Geant4/G4UserLimits.hh>
30 #include <Geant4/G4VPhysicalVolume.hh>
47 , m_Params(parameters)
48 , m_ActiveFlag(m_Params->get_int_param(
"active"))
49 , m_AbsorberActiveFlag(m_Params->get_int_param(
"absorberactive"))
50 , m_InnerCageRadius(m_Params->get_double_param(
"gas_inner_radius") *
cm - m_Params->get_double_param(
"cage_layer_9_thickness") *
cm - m_Params->get_double_param(
"cage_layer_8_thickness") *
cm - m_Params->get_double_param(
"cage_layer_7_thickness") *
cm - m_Params->get_double_param(
"cage_layer_6_thickness") *
cm - m_Params->get_double_param(
"cage_layer_5_thickness") *
cm - m_Params->get_double_param(
"cage_layer_4_thickness") *
cm - m_Params->get_double_param(
"cage_layer_3_thickness") *
cm - m_Params->get_double_param(
"cage_layer_2_thickness") *
cm - m_Params->get_double_param(
"cage_layer_1_thickness") *
cm)
51 , m_OuterCageRadius(m_Params->get_double_param(
"gas_outer_radius") *
cm + m_Params->get_double_param(
"cage_layer_9_thickness") *
cm + m_Params->get_double_param(
"cage_layer_8_thickness") *
cm + m_Params->get_double_param(
"cage_layer_7_thickness") *
cm + m_Params->get_double_param(
"cage_layer_6_thickness") *
cm + m_Params->get_double_param(
"cage_layer_5_thickness") *
cm + m_Params->get_double_param(
"cage_layer_4_thickness") *
cm + m_Params->get_double_param(
"cage_layer_3_thickness") *
cm + m_Params->get_double_param(
"cage_layer_2_thickness") *
cm + m_Params->get_double_param(
"cage_layer_1_thickness") *
cm)
91 if (std::isfinite(steplimits))
99 G4LogicalVolume *tpc_envelope_logic =
new G4LogicalVolume(tpc_envelope,
110 tpc_envelope_logic,
"tpc_envelope",
121 static std::map<int, std::string> tpcgasvolname =
133 material.push_back(
"G4_Ni");
134 thickness.push_back(.240 *
cm);
135 material.push_back(
"G4_Au");
136 thickness.push_back(.008 *
cm);
137 G4Material *temp =
nullptr;
146 G4LogicalVolume *tpc_window_logic =
new G4LogicalVolume(tpc_window,
158 G4VPhysicalVolume *tpc_window_phys =
new G4PVPlacement(0, G4ThreeVector(0, 0, 0),
159 tpc_window_logic,
"tpc_window",
168 double tpc_window_surface2_core_thickness = tpc_window_thickness - 2 * tpc_window_surface1_thickness;
169 double tpc_window_core_thickness = tpc_window_surface2_core_thickness - 2 * (tpc_window_surface2_thickness);
171 G4VSolid *tpc_window_surface2_core =
173 tpc_window_surface2_core_thickness / 2., 0., 2 * M_PI);
174 G4LogicalVolume *tpc_window_surface2_core_logic =
new G4LogicalVolume(tpc_window_surface2_core,
176 "tpc_window_surface2_core");
184 G4VPhysicalVolume *tpc_window_surface2_core_phys =
new G4PVPlacement(0, G4ThreeVector(0, 0, 0),
185 tpc_window_surface2_core_logic,
"tpc_window_surface2_core",
191 G4VSolid *tpc_window_core =
193 tpc_window_core_thickness / 2., 0., 2 * M_PI);
194 G4LogicalVolume *tpc_window_core_logic =
new G4LogicalVolume(tpc_window_core,
199 G4VPhysicalVolume *tpc_window_core_phys =
new G4PVPlacement(0, G4ThreeVector(0, 0, 0),
200 tpc_window_core_logic,
"tpc_window_core",
208 G4LogicalVolume *tpc_gas_logic =
new G4LogicalVolume(tpc_gas,
214 G4VPhysicalVolume *tpc_gas_phys =
new G4PVPlacement(0, G4ThreeVector(0, 0, (tpc_half_length + tpc_window_thickness) / 2.),
216 tpc_envelope,
false, PHG4TpcDefs::North,
OverlapCheck());
217 std::cout <<
"north copy no: " << tpc_gas_phys->GetCopyNo() << std::endl;
220 tpc_gas_phys =
new G4PVPlacement(0, G4ThreeVector(0, 0, -(tpc_half_length + tpc_window_thickness) / 2.),
222 tpc_envelope,
false, PHG4TpcDefs::South,
OverlapCheck());
224 std::cout <<
"south copy no: " << tpc_gas_phys->GetCopyNo() << std::endl;
227 #if G4VERSION_NUMBER >= 1033
228 const G4RegionStore *theRegionStore = G4RegionStore::GetInstance();
229 G4Region *tpcregion = theRegionStore->GetRegion(
"REGION_TPCGAS");
230 tpc_gas_logic->SetRegion(tpcregion);
231 tpcregion->AddRootLogicalVolume(tpc_gas_logic);
254 double hangerX = 21.193 *
inch;
255 double hangerY = 24.246*
inch;
256 double hangerDiameter = 2. *
inch;
257 double extra_length = 0.941*
inch;
262 G4VSolid *hangerSupport =
new G4Tubs(
"tpc_hanger_support", 0, hangerDiameter / 2., (6*inch)+extra_length, 0., 2 * M_PI);
263 G4LogicalVolume *hangerSupportLogic =
new G4LogicalVolume(hangerSupport,
265 "tpc_hanger_support");
267 double tpc_steel_location = (90 *
inch) / 2 - 3 *inch - extra_length / 2.0;
270 G4VPhysicalVolume *tpc_hanger_support_phys[4] = {
nullptr,
nullptr,
nullptr,
nullptr};
271 tpc_hanger_support_phys[0] =
new G4PVPlacement(0, G4ThreeVector(hangerX, hangerY, tpc_steel_location),
272 hangerSupportLogic,
"tpc_hanger_support_northleft",
274 tpc_hanger_support_phys[1] =
new G4PVPlacement(0, G4ThreeVector(-hangerX, hangerY, tpc_steel_location),
275 hangerSupportLogic,
"tpc_hanger_support_northright",
277 tpc_hanger_support_phys[2] =
new G4PVPlacement(0, G4ThreeVector(hangerX, hangerY, -tpc_steel_location),
278 hangerSupportLogic,
"tpc_hanger_support_southleft",
280 tpc_hanger_support_phys[3] =
new G4PVPlacement(0, G4ThreeVector(-hangerX, hangerY, -tpc_steel_location),
281 hangerSupportLogic,
"tpc_hanger_support_southright",
291 double hangerBeamInnerDiameter = 2.0 *
inch;
292 double hangerBeamOuterDiameter = 2.521 *
inch;
294 G4VSolid *hangerBeam =
new G4Tubs(
"tpc_hanger_beam", hangerBeamInnerDiameter / 2., hangerBeamOuterDiameter / 2., (90 * inch) / 2., 0., 2 * M_PI);
295 G4LogicalVolume *hangerBeamLogic =
new G4LogicalVolume(hangerBeam,
301 tpc_hanger_beam_phys[0] =
new G4PVPlacement(0, G4ThreeVector(hangerX, hangerY, 0),
302 hangerBeamLogic,
"tpc_hanger_beam_left",
304 tpc_hanger_beam_phys[1] =
new G4PVPlacement(0, G4ThreeVector(-hangerX, hangerY, 0),
305 hangerBeamLogic,
"tpc_hanger_beam_right",
321 double rodAngleStart = M_PI / 12.;
322 double rodAngularSpacing = 2 * M_PI / 12.;
323 double rodRadius = 31.5 *
inch;
324 double rodWallThickness = 1. / 8. *
inch;
325 double rodDiameter = 3. / 4. *
inch;
326 G4VSolid *tieRod =
new G4Tubs(
"tpc_tie_rod", rodDiameter / 2. - rodWallThickness, rodDiameter / 2., (
m_Params->
get_double_param(
"tpc_length") *
cm) / 2., 0., 2 * M_PI);
327 G4LogicalVolume *tieRodLogic =
new G4LogicalVolume(tieRod,
331 G4VPhysicalVolume *tpc_tie_rod_phys[12] = {
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
332 nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr};
334 std::ostringstream
name;
335 for (
int i = 0;
i < 12;
i++)
337 double ang = rodAngleStart + rodAngularSpacing *
i;
339 name <<
"tpc_tie_rod_" <<
i;
340 tpc_tie_rod_phys[
i] =
new G4PVPlacement(0, G4ThreeVector(rodRadius * cos(ang), rodRadius * sin(ang), 0),
341 tieRodLogic, name.str(),
385 std::ostringstream
name;
390 name <<
"tpc_cage_layer_" << layerno;
391 G4VSolid *tpc_cage_layer =
new G4Tubs(name.str(), tpc_cage_radius, tpc_cage_radius + thickness[
i],
m_Params->
get_double_param(
"tpc_length") *
cm / 2., 0., 2 * M_PI);
392 G4LogicalVolume *tpc_cage_layer_logic =
new G4LogicalVolume(tpc_cage_layer,
396 G4VPhysicalVolume *tpc_cage_layer_phys =
new G4PVPlacement(0, G4ThreeVector(0, 0, 0),
397 tpc_cage_layer_logic, name.str(),
400 tpc_cage_radius += thickness[
i];
407 tpc_cage_radius -= thickness[
i];
409 int layerno = 10 + 1 +
i;
410 name <<
"tpc_cage_layer_" << layerno;
411 G4VSolid *tpc_cage_layer =
new G4Tubs(name.str(), tpc_cage_radius, tpc_cage_radius + thickness[
i],
m_Params->
get_double_param(
"tpc_length") *
cm / 2., 0., 2 * M_PI);
412 G4LogicalVolume *tpc_cage_layer_logic =
new G4LogicalVolume(tpc_cage_layer,
416 G4VPhysicalVolume *tpc_cage_layer_phys =
new G4PVPlacement(0, G4ThreeVector(0, 0, 0),
417 tpc_cage_layer_logic, name.str(),
427 std::vector<std::string> materialName,
435 if (tempmat !=
nullptr)
437 std::cout << __PRETTY_FUNCTION__ <<
" Fatal Error: composite material " << compositeName <<
" already exists" << std::endl;
442 assert(materialName.size() == thickness.size());
445 double totalArealDensity = 0, totalThickness = 0;
446 for (std::vector<double>::size_type
i = 0;
i < thickness.size();
i++)
449 if (tempmat ==
nullptr)
451 std::cout << __PRETTY_FUNCTION__ <<
" Fatal Error: component material " << materialName[
i] <<
" does not exist." << std::endl;
455 totalArealDensity += tempmat->GetDensity() * thickness[
i];
456 totalThickness += thickness[
i];
460 double compositeDensity = totalArealDensity / totalThickness;
461 G4Material *composite =
new G4Material(compositeName, compositeDensity, thickness.size());
464 for (std::vector<double>::size_type
i = 0;
i < thickness.size();
i++)
467 composite->AddMaterial(tempmat, thickness[i] * tempmat->GetDensity() / totalArealDensity);
480 const std::string geonode_name =
"CYLINDERCELLGEOM_SVTX";
481 auto geonode = findNode::getClass<PHG4TpcCylinderGeomContainer>(
topNode(), geonode_name);
488 runNode->addNode(newNode);
491 const std::array<int, 3> NTpcLayers =
498 std::array<double, 3> MinLayer;
500 MinLayer[1] = MinLayer[0] + NTpcLayers[0];
501 MinLayer[2] = MinLayer[1] + NTpcLayers[1];
503 const std::array<double, 3> MinRadius =
510 const std::array<double, 3> MaxRadius =
517 const std::array<double, 5> Thickness =
529 const double TBinWidth = tpc_adc_clock;
531 const double MaxT = extended_readout_time + 2.* MaxZ / drift_velocity;
532 const double MinT = 0;
533 const int NTBins = (int) ((MaxT - MinT) / TBinWidth) + 1;
535 std::cout <<
PHWHERE <<
"MaxT " << MaxT <<
" NTBins = " << NTBins <<
" drift velocity " << drift_velocity << std::endl;
537 const std::array<double, 3> SectorPhi =
544 const std::array<int, 3> NPhiBins =
551 const std::array<double, 3> PhiBinWidth =
553 SectorPhi[0] * 12 / (
double) NPhiBins[0],
554 SectorPhi[1] * 12 / (
double) NPhiBins[1],
555 SectorPhi[2] * 12 / (
double) NPhiBins[2]
559 static constexpr
int NSides = 2;
562 std::array<std::vector<double>, NSides > sector_R_bias;
563 std::array<std::vector<double>, NSides > sector_Phi_bias;
564 std::array<std::vector<double>, NSides > sector_min_Phi;
565 std::array<std::vector<double>, NSides > sector_max_Phi;
568 for (
int iregion = 0; iregion < 3; ++iregion)
571 for (
int zside = 0; zside < 2;zside++)
573 sector_R_bias[zside].clear();
574 sector_Phi_bias[zside].clear();
575 sector_min_Phi[zside].clear();
576 sector_max_Phi[zside].clear();
578 for (
int isector = 0; isector <
NSectors; ++isector)
583 sector_R_bias[zside].push_back(0);
584 sector_Phi_bias[zside].push_back(0);
586 double sec_gap = (2*M_PI - SectorPhi[iregion]*12)/12;
587 double sec_max_phi = M_PI - SectorPhi[iregion]/2 - sec_gap - 2 * M_PI / 12 * isector;
588 double sec_min_phi = sec_max_phi - SectorPhi[iregion];
589 sector_min_Phi[zside].push_back(sec_min_phi);
590 sector_max_Phi[zside].push_back(sec_max_phi);
595 for (
int layer = MinLayer[iregion];
layer < MinLayer[iregion] + NTpcLayers[iregion]; ++
layer)
597 double r_length = Thickness[iregion];
598 if(iregion == 0 &&
layer>0){
599 if(
layer%2==0) r_length = Thickness[4];
600 else r_length = Thickness[3];
604 const double pad_space = (MaxRadius[iregion] - MinRadius[iregion] - sum_r)/(NTpcLayers[iregion]-1);
605 double current_r = MinRadius[iregion];
607 for (
int layer = MinLayer[iregion];
layer < MinLayer[iregion] + NTpcLayers[iregion]; ++
layer)
611 std::cout <<
" layer " <<
layer <<
" MinLayer " << MinLayer[iregion] <<
" region " << iregion
612 <<
" radius " << MinRadius[iregion] + ((
double) (
layer - MinLayer[iregion]) + 0.5) * Thickness[iregion]
613 <<
" thickness " << Thickness[iregion]
614 <<
" NTBins " << NTBins <<
" tmin " << MinT <<
" tstep " << TBinWidth
615 <<
" phibins " << NPhiBins[iregion] <<
" phistep " << PhiBinWidth[iregion] << std::endl;
621 double r_length = Thickness[iregion];
622 if(iregion == 0 &&
layer>0)
624 if(
layer%2==0) r_length = Thickness[4];
625 else r_length = Thickness[3];
627 layerseggeo->set_thickness(r_length);
628 layerseggeo->set_radius(current_r+r_length/2);
630 layerseggeo->set_zbins(NTBins);
631 layerseggeo->set_zmin(MinT);
632 layerseggeo->set_zstep(TBinWidth);
633 layerseggeo->set_phibins(NPhiBins[iregion]);
634 layerseggeo->set_phistep(PhiBinWidth[iregion]);
635 layerseggeo->set_r_bias(sector_R_bias);
636 layerseggeo->set_phi_bias(sector_Phi_bias);
637 layerseggeo->set_sector_min_phi(sector_min_Phi);
638 layerseggeo->set_sector_max_phi(sector_max_Phi);
642 if (NPhiBins[iregion] * NTBins > 5100000)
644 std::cout <<
"increase Tpc cellsize, number of cells "
645 << NPhiBins[iregion] * NTBins <<
" for layer " <<
layer
646 <<
" exceed 5.1M limit" << std::endl;
649 geonode->AddLayerCellGeom(layerseggeo);
651 current_r += r_length + pad_space;