12 #include <phparameter/PHParameters.h>
29 #include <Geant4/G4Box.hh>
30 #include <Geant4/G4Color.hh>
31 #include <Geant4/G4LogicalVolume.hh>
32 #include <Geant4/G4Material.hh>
33 #include <Geant4/G4PVPlacement.hh>
34 #include <Geant4/G4String.hh>
35 #include <Geant4/G4SystemOfUnits.hh>
36 #include <Geant4/G4ThreeVector.hh>
37 #include <Geant4/G4Tubs.hh>
38 #include <Geant4/G4Types.hh>
39 #include <Geant4/G4VPhysicalVolume.hh>
40 #include <Geant4/G4VSolid.hh>
67 , m_Params(parameters)
68 , m_ActiveFlag(m_Params->get_int_param(
"active"))
69 , m_SupportActiveFlag(m_Params->get_int_param(
"supportactive"))
105 return iter ==
m_tiles_map.end() ? -1 : iter->second;
119 std::cout <<
"PHG4Micromegas Detector:" << std::endl;
120 if (what ==
"ALL" || what ==
"VOLUME")
122 std::cout <<
"Version 0.1" << std::endl;
123 std::cout <<
"Parameters:" << std::endl;
137 static constexpr
double tile_length = 54.2;
138 static constexpr
double tile_width = 31.6;
142 static constexpr
double phi = 3. * M_PI / 2;
145 for (
const double& tile_z : {-84.6, -28.2, 28.2, 84.6})
153 for (
const double&
phi : {4. * M_PI / 3, 5. * M_PI / 3})
156 for (
const double& tile_z : {-37.1, 37.1})
183 static const G4double temperature = 298.15 * kelvin;
184 static const G4double pressure = 1. * atmosphere;
189 auto mmg_FR4 =
new G4Material(
"mmg_FR4", 1.860 *
g /
cm3, 4, kStateSolid);
190 mmg_FR4->AddMaterial(G4_C, 0.43550);
191 mmg_FR4->AddMaterial(G4_H, 0.03650);
192 mmg_FR4->AddMaterial(G4_O, 0.28120);
193 mmg_FR4->AddMaterial(G4_Si, 0.24680);
199 auto mmg_Kapton =
new G4Material(
"mmg_Kapton", 1.420 *
g /
cm3, 4, kStateSolid);
200 mmg_Kapton->AddMaterial(G4_C, 0.6911330);
201 mmg_Kapton->AddMaterial(G4_H, 0.0263620);
202 mmg_Kapton->AddMaterial(G4_N, 0.0732700);
203 mmg_Kapton->AddMaterial(G4_O, 0.2092350);
209 auto mmg_Gas =
new G4Material(
"mmg_Gas", 0.00170335 *
g /
cm3, 3, kStateGas, temperature, pressure);
210 mmg_Gas->AddMaterial(G4_Ar, 0.900);
211 mmg_Gas->AddMaterial(G4_C, 0.0826586);
212 mmg_Gas->AddMaterial(G4_H, 0.0173414);
218 auto mmg_Mesh =
new G4Material(
"mmg_Mesh", 2.8548 *
g /
cm3, 5, kStateSolid);
219 mmg_Mesh->AddMaterial(G4_Cr, 0.1900);
220 mmg_Mesh->AddMaterial(G4_Fe, 0.6800);
221 mmg_Mesh->AddMaterial(G4_Mn, 0.0200);
222 mmg_Mesh->AddMaterial(G4_Ni, 0.1000);
223 mmg_Mesh->AddMaterial(G4_Si, 0.0100);
229 new G4Material(
"mmg_Strips", 5.248414 *
g /
cm3, G4_Cu, kStateSolid);
235 new G4Material(
"mmg_ResistPaste", 0.77906 *
g /
cm3, G4_C, kStateSolid);
251 double radius_phi_mean = 0;
252 double radius_z_mean = 0;
256 static constexpr
bool apply_survey =
true;
260 for (
size_t tileid = 0; tileid <
m_tiles.size(); ++tileid)
267 const double tile_thickness_phi =
static_cast<G4Box*
>(tile_logic_phi->GetSolid())->GetXHalfLength() * 2;
271 const double centerZ =
tile.m_centerZ *
cm;
272 const double centerPhi =
tile.m_centerPhi;
274 G4RotationMatrix rotation;
275 rotation.rotateZ(centerPhi * radian);
278 double radius_phi = inner_radius + tile_thickness_phi / 2;
279 const G4ThreeVector center(
280 radius_phi * std::cos(centerPhi),
281 radius_phi * std::sin(centerPhi),
284 G4Transform3D
transform(rotation, center);
290 transform = survey_transform *
transform;
293 const auto translation = transform.getTranslation();
298 radius_phi_mean += radius_phi;
301 new G4PVPlacement(transform, tile_logic_phi, tilename +
"_phys", logicWorld,
false, 0,
OverlapCheck());
306 const double tile_thickness_z =
static_cast<G4Box*
>(tile_logic_z->GetSolid())->GetXHalfLength() * 2;
310 const double centerZ =
tile.m_centerZ *
cm;
311 const double centerPhi =
tile.m_centerPhi;
313 G4RotationMatrix rotation;
314 rotation.rotateZ(centerPhi * radian);
316 double radius_z = inner_radius + tile_thickness_phi + tile_thickness_z / 2;
317 const G4ThreeVector center(
318 radius_z * std::cos(centerPhi),
319 radius_z * std::sin(centerPhi),
322 G4Transform3D
transform(rotation, center);
328 transform = survey_transform *
transform;
331 const auto translation = transform.getTranslation();
335 radius_z_mean += radius_z;
338 new G4PVPlacement(transform, tile_logic_z, tilename +
"_phys", logicWorld,
false, 0,
OverlapCheck());
343 radius_phi_mean /=
m_tiles.size();
346 radius_z_mean /=
m_tiles.size();
351 std::cout <<
"PHG4MicromegasDetector::ConstructMe - first layer: " <<
m_FirstLayer << std::endl;
354 std::cout <<
"PHG4MicromegasDetector::ConstructMe - layer: " << pair.second <<
" volume: " << pair.first->GetName() << std::endl;
389 : m_thickness(thickness)
390 , m_material(material)
394 , m_y_offset(y_offset)
395 , m_z_offset(z_offset)
400 float m_thickness = 0;
403 G4Material* m_material =
nullptr;
406 G4Colour m_color = 0;
415 double m_y_offset = 0;
418 double m_z_offset = 0;
422 const std::map<Component, LayerStruct> layer_map =
427 {Component::CuStrips, LayerStruct(12. * micrometer,
GetDetectorMaterial(
"mmg_Strips"), G4Colour::Brown(), 256 *
mm, 512 *
mm, -15 *
mm, 0)},
428 {Component::KaptonStrips, LayerStruct(50. * micrometer,
GetDetectorMaterial(
"mmg_Kapton"), G4Colour::Brown(), 256 *
mm, 512 *
mm, -15 *
mm, 0)},
429 {Component::ResistiveStrips, LayerStruct(20. * micrometer,
GetDetectorMaterial(
"mmg_ResistPaste"), G4Colour::Black(), 256 *
mm, 512 *
mm, -15 *
mm, 0)},
430 {Component::Gas1, LayerStruct(120. * micrometer,
GetDetectorMaterial(
"mmg_Gas"), G4Colour::Grey(), 256 *
mm, 512 *
mm, -15 *
mm, 0)},
432 {Component::Mesh, LayerStruct(18. * 0.8 * micrometer,
GetDetectorMaterial(
"mmg_Mesh"), G4Colour::White(), 256 *
mm, 512 *
mm, -15 *
mm, 0)},
434 {Component::DriftCuElectrode, LayerStruct(15. * micrometer,
GetDetectorMaterial(
"G4_Cu"), G4Colour::Brown(), 256 *
mm, 512 *
mm, -15 *
mm, 0)},
435 {Component::DriftKapton, LayerStruct(50. * micrometer,
GetDetectorMaterial(
"mmg_Kapton"), G4Colour::Brown(), 256 *
mm, 512 *
mm, -15 *
mm, 0)},
436 {Component::DriftCarbon, LayerStruct(1. *
mm,
GetDetectorMaterial(
"G4_C"), G4Colour(150 / 255., 75 / 255., 0), 256 *
mm, 512 *
mm, -15 *
mm, 0)},
440 using LayerDefinition = std::tuple<Component, std::string>;
441 const std::vector<LayerDefinition> layer_stack_phi =
446 std::make_tuple(Component::DriftCuElectrode,
"DriftCuElectrode_inner"),
456 const std::vector<LayerDefinition> layer_stack_z =
466 std::make_tuple(Component::DriftCuElectrode,
"DriftCuElectrode_outer"),
476 const auto& layer_stack = is_z ? layer_stack_z : layer_stack_phi;
479 std::array<G4LogicalVolume*, 2> fee_board_logic =
484 const double fee_thickness = is_z ?
static_cast<G4Box*
>(fee_board_logic[0]->GetSolid())->GetXHalfLength() * 2 : 0;
487 double tile_thickness = std::accumulate(
488 layer_stack.begin(), layer_stack.end(), 0.,
489 [&layer_map](
double value,
const LayerDefinition&
layer)
490 {
return value + layer_map.at(std::get<0>(
layer)).m_thickness; });
495 tile_thickness += fee_thickness;
499 const double tile_dy = layer_map.at(Component::PCB).m_dy;
500 const double tile_dz = layer_map.at(Component::PCB).m_dz;
509 auto tile_solid =
new G4Box(tilename +
"_solid", tile_thickness / 2, tile_dy / 2, tile_dz / 2);
510 auto tile_logic =
new G4LogicalVolume(tile_solid, world_material,
"invisible_" + tilename +
"_logic");
514 auto current_radius_local = -tile_thickness / 2;
515 for (
const auto& [
type,
name] : layer_stack)
522 const G4String cname = (
type == Component::Gas2) ?
"micromegas_measurement_" +
name : G4String(
GetName()) +
"_" +
name;
525 const auto& component(layer_map.at(
type));
526 const auto&
thickness = component.m_thickness;
527 const auto&
material = component.m_material;
528 const auto&
color = component.m_color;
530 const auto&
dy = component.m_dy;
531 const auto&
dz = component.m_dz;
533 const auto& y_offset = component.m_y_offset;
534 const auto&
z_offset = component.m_z_offset;
536 auto component_solid =
new G4Box(cname +
"_solid", thickness / 2,
dy / 2,
dz / 2);
537 auto component_logic =
new G4LogicalVolume(component_solid,
material, cname +
"_logic");
540 const G4ThreeVector center((current_radius_local + thickness / 2), y_offset,
z_offset);
541 auto component_phys =
new G4PVPlacement(
nullptr, center, component_logic, cname +
"_phys", tile_logic,
false, 0,
OverlapCheck());
543 if (
type == Component::Gas2)
549 m_tiles_map.insert(std::make_pair(component_phys, tileid));
552 m_layer_radius.insert(std::make_pair(layer_index, (current_radius_local + thickness / 2) /
cm));
568 static constexpr
double fee_y_offset = (316. / 2 - 44.7 - 141.5 / 2) *
mm;
569 static constexpr
double fee_x_offset = (542. / 2 - 113.1 - 140. / 2) *
mm;
570 new G4PVPlacement(
nullptr, {current_radius_local + fee_thickness / 2, -fee_y_offset, -fee_x_offset}, fee_board_logic[0],
GetName() +
"_fee_0_phys", tile_logic,
false, 0,
OverlapCheck());
571 new G4PVPlacement(
nullptr, {current_radius_local + fee_thickness / 2, -fee_y_offset, fee_x_offset}, fee_board_logic[1],
GetName() +
"_fee_1_phys", tile_logic,
false, 0,
OverlapCheck());
587 , m_thickness(thickness)
588 , m_material(material)
597 float m_thickness = 0;
600 G4Material* m_material =
nullptr;
603 G4Colour m_color = 0;
606 static constexpr
double inch_to_cm = 2.54;
613 const std::vector<LayerStruct> layer_stack = {
616 LayerStruct(
"fee_al", 0.25 * inch_to_cm * cm,
GetDetectorMaterial(
"G4_Al"), G4Colour::Grey())};
619 const double fee_thickness = std::accumulate(
620 layer_stack.begin(), layer_stack.end(), 0.,
622 {
return value +
layer.m_thickness; });
625 const double fee_dy = 141.51 *
mm;
626 const double fee_dz = 140 *
mm;
635 auto fee_solid =
new G4Box(feename +
"_solid", fee_thickness / 2, fee_dy / 2, fee_dz / 2);
636 auto fee_logic =
new G4LogicalVolume(fee_solid, world_material,
"invisible_" + feename +
"_logic");
640 auto current_radius_local = -fee_thickness / 2;
641 for (
const auto&
layer : layer_stack)
648 const G4String cname = G4String(
GetName()) +
"_" +
layer.m_name;
655 auto component_solid =
new G4Box(cname +
"_solid",
thickness / 2, fee_dy / 2, fee_dz / 2);
656 auto component_logic =
new G4LogicalVolume(component_solid,
material, cname +
"_logic");
659 const G4ThreeVector center((current_radius_local +
thickness / 2), 0, 0);
660 auto component_phys =
new G4PVPlacement(
nullptr, center, component_logic, cname +
"_phys", fee_logic,
false, 0,
OverlapCheck());
684 auto geonode = findNode::getClass<PHG4CylinderGeomContainer>(
topNode(), geonode_name);
691 runNode->addNode(newNode);
695 static constexpr
double length = 220;
699 bool is_first =
true;
705 cylinder->set_radius(radius);
707 cylinder->set_zmin(-length / 2);
708 cylinder->set_zmax(length / 2);
724 cylinder->set_drift_direction(is_first ? MicromegasDefs::DriftDirection::OUTWARD : MicromegasDefs::DriftDirection::INWARD);
728 cylinder->set_pitch(is_first ? 0.1 : 0.2);
732 cylinder->identify(std::cout);
735 geonode->AddLayerGeom(layer_index, cylinder);