Belle II Software development
GeoBKLMCreator Class Reference

This class creates the BKLM geometry of the Belle II detector. More...

#include <GeoBKLMCreator.h>

Inheritance diagram for GeoBKLMCreator:
CreatorBase

Public Member Functions

 GeoBKLMCreator ()
 Constructor of the GeoBKLMCreator class.
 
 GeoBKLMCreator (GeoBKLMCreator &)=delete
 Copy constructor is disabled.
 
GeoBKLMCreatoroperator= (GeoBKLMCreator &)=delete
 Assignment operator is disabled.
 
 ~GeoBKLMCreator ()
 Destructor of the GeoBKLMCreator class.
 
void create (const GearDir &content, G4LogicalVolume &topVolume, geometry::GeometryTypes type) override
 Creates the objects for the BKLM geometry virtual void create(const GearDir&, G4LogicalVolume&, geometry::GeometryTypes type);.
 
void createPayloads (const GearDir &content, const IntervalOfValidity &iov) override
 Create the configuration objects and save them in the Database.
 
void createFromDB (const std::string &name, G4LogicalVolume &topVolume, geometry::GeometryTypes type) override
 Create the geometry from the Database.
 
 BELLE2_DEFINE_EXCEPTION (DBNotImplemented, "Cannot create geometry from Database.")
 Exception that will be thrown in createFromDB if member is not yet implemented by creator.
 

Private Member Functions

BKLMGeometryPar createConfiguration (const GearDir &param)
 Create a parameter object from the Gearbox XML parameters.
 
void createGeometry (const BKLMGeometryPar &parameters, G4LogicalVolume &topVolume, geometry::GeometryTypes type)
 Create the geometry from a parameter object.
 
void putEndsInEnvelope (G4LogicalVolume *)
 Put the forward and backward ends into the BKLM envelope.
 
void putSectorsInEnd (G4LogicalVolume *, int)
 Put each sector into the forward or backward end.
 
void putCapInSector (G4LogicalVolume *, bool)
 Put the cap (at maximum |z|) into each sector.
 
void putInnerRegionInSector (G4LogicalVolume *, bool, bool)
 Put the inner-radius region into each sector.
 
void putVoidInInnerRegion (G4LogicalVolume *, bool, bool)
 Put the air void into the inner-radius region.
 
void putLayer1SupportInInnerVoid (G4LogicalVolume *, bool)
 Put the layer-0 support plate into the inner region's air void (sectors 1..5 only)
 
void putLayer1BracketsInInnerVoid (G4LogicalVolume *, bool)
 Put the layer-0 support plate's brackets into the inner region's air void (sectors 1..5 only)
 
void putLayersInSector (G4LogicalVolume *, int, int, bool)
 Put the layers into each sector.
 
void putChimneyInLayer (G4LogicalVolume *, int)
 Put the solenoid's cooling chimney into the backward top sector.
 
void putModuleInLayer (G4LogicalVolume *, int, int, int, bool, bool, int)
 Put the module (and enclosing air gap) into each layer.
 
void putRPCsInInterior (G4LogicalVolume *, int, bool)
 Put the RPCs into each detector module's interior (module is itself in an air gap)
 
void putScintsInInterior (G4LogicalVolume *, int, int, int, bool)
 Put the scintillators into each detector module's interior (module is itself in an air gap)
 
G4LogicalVolume * getScintLogical (double, double, double, double)
 Get pointer to scintillator logical volume.
 
G4LogicalVolume * getMPPCHousingLogical (void)
 Get pointer to MPPC-container logical volume.
 
G4LogicalVolume * getReadoutContainerLogical (void)
 Get pointer to readout-container logical volume.
 
G4Tubs * getSolenoidTube (void)
 Get shape corresponding to the solenoid (for subtraction)
 
G4String logicalName (G4VSolid *)
 convert G4VSolid's name to corresponding G4LogicalVolume name
 
G4String physicalName (G4LogicalVolume *)
 convert G4LogicalVolume's name to corresponding G4PhysicalVolume name
 

Private Attributes

GeometryParm_GeoPar
 Pointer to the BKLM geometry accessor.
 
G4VSensitiveDetector * m_Sensitive
 Pointer to the BKLM SensitiveDetector processor.
 
double m_SectorDphi
 Angular extent of one sector.
 
double m_SectorDz
 Half-length of one sector.
 
double m_RibShift
 Radial displacement of polygon to create an azimuthal iron rib.
 
G4Polyhedra * m_CapSolid
 Pointer to solid for cap.
 
G4LogicalVolume * m_CapLogical [2]
 Pointer to logical volumes for cap [hasChimney].
 
G4VSolid * m_InnerIronSolid
 Pointer to solid for inner iron [hasInnerSupport | hasChimney].
 
G4LogicalVolume * m_InnerIronLogical [4]
 Pointer to logical volumes for inner iron [hasInnerSupport | hasChimney].
 
G4VSolid * m_InnerAirSolid
 Pointer to solid for inner air.
 
G4LogicalVolume * m_InnerAirLogical [4]
 Pointer to logical volumes for inner air [hasInnerSupport | hasChimney].
 
G4LogicalVolume * m_SupportLogical [2]
 Pointer to logical volumes for support structure [hasChimney].
 
G4LogicalVolume * m_BracketLogical
 Pointer to logical volume for bracket.
 
G4Polyhedra * m_LayerIronSolid [BKLMElementNumbers::getMaximalLayerNumber()]
 Pointers to solids for iron in each layer [layer-1].
 
G4LogicalVolume * m_LayerIronLogical [12 *BKLMElementNumbers::getMaximalLayerNumber()]
 Pointers to logical volumes for iron in each layer [side/bottom/top | isFlipped | hasChimney | layer-1].
 
G4Box * m_LayerGapSolid [2 *BKLMElementNumbers::getMaximalLayerNumber()]
 Pointers to solids for air gap in each layer [hasChimney | layer-1].
 
G4LogicalVolume * m_LayerGapLogical [12 *BKLMElementNumbers::getMaximalLayerNumber()]
 Pointers to logical volumes for air gap in each layer [side/bottom/top | isFlipped | hasChimney | layer-1].
 
G4LogicalVolume * m_LayerModuleLogical [2 *BKLMElementNumbers::getMaximalLayerNumber()]
 Pointers to logical volumes for detector modules in each layer's air gap [hasChimney | layer-1].
 
G4Tubs * m_SectorTube
 Pointer to solid for sector's enclosing tube.
 
G4LogicalVolume * m_SectorLogical [2][BKLMElementNumbers::getMaximalSectorNumber()]
 Pointers to logical volumes for each sector [fb-1][sector-1].
 
G4LogicalVolume * m_MPPCHousingLogical
 Pointer to logical volume for MPPC housing.
 
G4LogicalVolume * m_ReadoutContainerLogical
 Pointer to logical volume for scint preamplifier/carrier container.
 
G4Tubs * m_SolenoidTube
 Pointer to solid for solenoid.
 
std::vector< G4LogicalVolume * > m_ScintLogicals
 Pointers to logical volumes for scintillator strips.
 
std::vector< G4VisAttributes * > m_VisAttributes
 Vector of pointers to G4VisAttributes objects.
 
std::vector< G4String * > m_Names
 Vector of pointers to G4String objects (volume names)
 

Detailed Description

This class creates the BKLM geometry of the Belle II detector.

Definition at line 43 of file GeoBKLMCreator.h.

Constructor & Destructor Documentation

◆ GeoBKLMCreator()

Constructor of the GeoBKLMCreator class.

Definition at line 41 of file GeoBKLMCreator.cc.

42{
43 m_Sensitive = dynamic_cast<G4VSensitiveDetector*>(new KLM::SensitiveDetector(G4String("BKLM"), KLMElementNumbers::c_BKLM));
44 m_GeoPar = nullptr;
45 m_SectorDphi = 0.0;
46 m_SectorDz = 0.0;
47 m_RibShift = 0.0;
48 m_CapSolid = nullptr;
49 m_CapLogical[0] = m_CapLogical[1] = nullptr;
50 m_InnerIronSolid = nullptr;
52 m_InnerAirSolid = nullptr;
54 m_SupportLogical[0] = m_SupportLogical[1] = nullptr;
55 m_BracketLogical = nullptr;
56 for (int j = 0; j < BKLMElementNumbers::getMaximalLayerNumber(); ++j) {
57 m_LayerIronSolid[j] = nullptr;
58 }
59 for (int j = 0; j < 2 * BKLMElementNumbers::getMaximalLayerNumber(); ++j) {
60 m_LayerModuleLogical[j] = nullptr;
61 m_LayerGapSolid[j] = nullptr;
62 }
63 for (int j = 0; j < 12 * BKLMElementNumbers::getMaximalLayerNumber(); ++j) {
64 m_LayerIronLogical[j] = nullptr;
65 m_LayerGapLogical[j] = nullptr;
66 }
67 m_SectorTube = nullptr;
68 for (int sector = 0; sector < BKLMElementNumbers::getMaximalSectorNumber(); ++sector) {
69 m_SectorLogical[0][sector] = nullptr;
70 m_SectorLogical[1][sector] = nullptr;
71 }
72 m_MPPCHousingLogical = nullptr;
74 m_SolenoidTube = nullptr;
75 m_ScintLogicals.clear();
76 m_VisAttributes.clear();
77 m_VisAttributes.push_back(new G4VisAttributes(false)); // for "invisible"
78 m_Names.clear();
79}
static constexpr int getMaximalLayerNumber()
Get maximal layer number (1-based).
static constexpr int getMaximalSectorNumber()
Get maximal sector number (1-based).
G4LogicalVolume * m_LayerGapLogical[12 *BKLMElementNumbers::getMaximalLayerNumber()]
Pointers to logical volumes for air gap in each layer [side/bottom/top | isFlipped | hasChimney | lay...
G4LogicalVolume * m_SupportLogical[2]
Pointer to logical volumes for support structure [hasChimney].
G4Tubs * m_SolenoidTube
Pointer to solid for solenoid.
G4LogicalVolume * m_ReadoutContainerLogical
Pointer to logical volume for scint preamplifier/carrier container.
G4LogicalVolume * m_BracketLogical
Pointer to logical volume for bracket.
G4Polyhedra * m_CapSolid
Pointer to solid for cap.
G4LogicalVolume * m_SectorLogical[2][BKLMElementNumbers::getMaximalSectorNumber()]
Pointers to logical volumes for each sector [fb-1][sector-1].
double m_SectorDphi
Angular extent of one sector.
G4Tubs * m_SectorTube
Pointer to solid for sector's enclosing tube.
G4Box * m_LayerGapSolid[2 *BKLMElementNumbers::getMaximalLayerNumber()]
Pointers to solids for air gap in each layer [hasChimney | layer-1].
double m_RibShift
Radial displacement of polygon to create an azimuthal iron rib.
std::vector< G4VisAttributes * > m_VisAttributes
Vector of pointers to G4VisAttributes objects.
G4LogicalVolume * m_MPPCHousingLogical
Pointer to logical volume for MPPC housing.
G4VSolid * m_InnerIronSolid
Pointer to solid for inner iron [hasInnerSupport | hasChimney].
double m_SectorDz
Half-length of one sector.
G4Polyhedra * m_LayerIronSolid[BKLMElementNumbers::getMaximalLayerNumber()]
Pointers to solids for iron in each layer [layer-1].
G4LogicalVolume * m_InnerAirLogical[4]
Pointer to logical volumes for inner air [hasInnerSupport | hasChimney].
G4LogicalVolume * m_CapLogical[2]
Pointer to logical volumes for cap [hasChimney].
G4LogicalVolume * m_InnerIronLogical[4]
Pointer to logical volumes for inner iron [hasInnerSupport | hasChimney].
G4VSensitiveDetector * m_Sensitive
Pointer to the BKLM SensitiveDetector processor.
std::vector< G4LogicalVolume * > m_ScintLogicals
Pointers to logical volumes for scintillator strips.
G4LogicalVolume * m_LayerIronLogical[12 *BKLMElementNumbers::getMaximalLayerNumber()]
Pointers to logical volumes for iron in each layer [side/bottom/top | isFlipped | hasChimney | layer-...
GeometryPar * m_GeoPar
Pointer to the BKLM geometry accessor.
G4VSolid * m_InnerAirSolid
Pointer to solid for inner air.
std::vector< G4String * > m_Names
Vector of pointers to G4String objects (volume names)
G4LogicalVolume * m_LayerModuleLogical[2 *BKLMElementNumbers::getMaximalLayerNumber()]
Pointers to logical volumes for detector modules in each layer's air gap [hasChimney | layer-1].

◆ ~GeoBKLMCreator()

Destructor of the GeoBKLMCreator class.

Definition at line 81 of file GeoBKLMCreator.cc.

82{
83 delete m_Sensitive;
84 m_ScintLogicals.clear();
85 for (G4VisAttributes* visAttr : m_VisAttributes) delete visAttr;
86 m_VisAttributes.clear();
87 for (G4String* name : m_Names) delete name;
88 m_Names.clear();
89}

Member Function Documentation

◆ create()

void create ( const GearDir content,
G4LogicalVolume &  topVolume,
geometry::GeometryTypes  type 
)
inlineoverridevirtual

Creates the objects for the BKLM geometry virtual void create(const GearDir&, G4LogicalVolume&, geometry::GeometryTypes type);.

Implements CreatorBase.

Definition at line 61 of file GeoBKLMCreator.h.

62 {
63 BKLMGeometryPar config = createConfiguration(content);
64 createGeometry(config, topVolume, type);
65 }
BKLMGeometryPar createConfiguration(const GearDir &param)
Create a parameter object from the Gearbox XML parameters.
void createGeometry(const BKLMGeometryPar &parameters, G4LogicalVolume &topVolume, geometry::GeometryTypes type)
Create the geometry from a parameter object.

◆ createConfiguration()

BKLMGeometryPar createConfiguration ( const GearDir param)
inlineprivate

Create a parameter object from the Gearbox XML parameters.

Definition at line 91 of file GeoBKLMCreator.h.

92 {
93 BKLMGeometryPar bklmGeometryPar;
94 //bklmGeometryPar.setVersion(0);
95 bklmGeometryPar.read(param);
96 return bklmGeometryPar;
97 };

◆ createFromDB()

void createFromDB ( const std::string &  name,
G4LogicalVolume &  topVolume,
geometry::GeometryTypes  type 
)
inlineoverridevirtual

Create the geometry from the Database.

Check that we found the object and if not report the problem

Reimplemented from CreatorBase.

Definition at line 76 of file GeoBKLMCreator.h.

77 {
78 DBObjPtr<BKLMGeometryPar> dbObj;
79 if (!dbObj) {
81 B2FATAL("No configuration for " << name << " found.");
82 }
83 createGeometry(*dbObj, topVolume, type);
84 }

◆ createGeometry()

void createGeometry ( const BKLMGeometryPar parameters,
G4LogicalVolume &  topVolume,
geometry::GeometryTypes  type 
)
private

Create the geometry from a parameter object.

Definition at line 95 of file GeoBKLMCreator.cc.

96{
97
98 m_GeoPar = GeometryPar::instance(parameters);
99 m_SectorDphi = 2.0 * M_PI / m_GeoPar->getNSector();
100 m_SectorDz = 0.5 * m_GeoPar->getHalfLength() * CLHEP::cm;
101 m_RibShift = 0.5 * m_GeoPar->getRibThickness() * CLHEP::cm / sin(0.5 * m_SectorDphi);
102
103 // Place BKLM envelope in mother volume
104 G4Tubs* envelopeSolid =
105 new G4Tubs("BKLM.EnvelopeSolid",
106 m_GeoPar->getSolenoidOuterRadius() * CLHEP::cm,
107 m_GeoPar->getOuterRadius() * CLHEP::cm / cos(0.5 * m_SectorDphi),
108 2.0 * m_SectorDz,
109 0.0,
110 2.0 * M_PI
111 );
112 G4LogicalVolume* envelopeLogical =
113 new G4LogicalVolume(envelopeSolid,
114 Materials::get("G4_AIR"),
115 "BKLM.EnvelopeLogical"
116 );
117 envelopeLogical->SetVisAttributes(m_VisAttributes.front()); // invisible
118 putEndsInEnvelope(envelopeLogical);
119 /* Set up region for production cuts. */
120 G4Region* aRegion = new G4Region("BKLMEnvelope");
121 envelopeLogical->SetRegion(aRegion);
122 aRegion->AddRootLogicalVolume(envelopeLogical);
123
124 new G4PVPlacement(G4TranslateZ3D(m_GeoPar->getOffsetZ() * CLHEP::cm) * G4RotateZ3D(m_GeoPar->getRotation() * CLHEP::rad),
125 envelopeLogical,
126 "BKLM.EnvelopePhysical",
127 &motherLogical,
128 false,
129 1,
130 false
131 );
132
133}
void putEndsInEnvelope(G4LogicalVolume *)
Put the forward and backward ends into the BKLM envelope.
double getOuterRadius(void) const
Get the radius of the inscribed circle of the outer polygon.
Definition: GeometryPar.h:187
double getOffsetZ(void) const
Get the global shift along a of the entire BKLM.
Definition: GeometryPar.h:157
double getRibThickness(void) const
Get the thickness of the radial rib that supports the solenoid / inner detectors.
Definition: GeometryPar.h:421
int getNSector(void) const
Get the number of sectors of the BKLM.
Definition: GeometryPar.h:175
double getRotation(void) const
Get the global rotation angle about z of the entire BKLM.
Definition: GeometryPar.h:151
double getHalfLength(void) const
Get the half-length along z of the BKLM.
Definition: GeometryPar.h:181
static GeometryPar * instance(void)
Static method to get a reference to the singleton GeometryPar instance.
Definition: GeometryPar.cc:27
double getSolenoidOuterRadius(void) const
Get the outer radius of the solenoid.
Definition: GeometryPar.h:169
static G4Material * get(const std::string &name)
Find given material.
Definition: Materials.h:63

◆ createPayloads()

void createPayloads ( const GearDir content,
const IntervalOfValidity iov 
)
inlineoverridevirtual

Create the configuration objects and save them in the Database.

Reimplemented from CreatorBase.

Definition at line 68 of file GeoBKLMCreator.h.

69 {
70 DBImportObjPtr<BKLMGeometryPar> importObj;
71 importObj.construct(createConfiguration(content));
72 importObj.import(iov);
73 }

◆ getMPPCHousingLogical()

G4LogicalVolume * getMPPCHousingLogical ( void  )
private

Get pointer to MPPC-container logical volume.

Definition at line 1072 of file GeoBKLMCreator.cc.

1073{
1074 if (m_MPPCHousingLogical == nullptr) {
1075 G4Tubs* mppcHousingSolid =
1076 new G4Tubs("BKLM.MPPCHousingSolid",
1077 0.0,
1078 m_GeoPar->getMPPCHousingRadius() * CLHEP::cm,
1079 m_GeoPar->getMPPCHousingHalfLength() * CLHEP::cm,
1080 0.0,
1081 2.0 * M_PI
1082 );
1084 new G4LogicalVolume(mppcHousingSolid,
1085 Materials::get("G4_POLYCARBONATE"),
1086 "BKLM>MPPCHousingLogical"
1087 );
1088 m_VisAttributes.push_back(new G4VisAttributes(true));
1089 m_VisAttributes.back()->SetColour(0.5, 0.5, 0.5); // gray
1090 m_MPPCHousingLogical->SetVisAttributes(m_VisAttributes.back());
1091 G4Box* mppcBox =
1092 new G4Box("BKLM.MPPCSolid",
1093 m_GeoPar->getMPPCHalfLength() * CLHEP::cm,
1094 m_GeoPar->getMPPCHalfWidth() * CLHEP::cm,
1095 m_GeoPar->getMPPCHalfHeight() * CLHEP::cm
1096 );
1097 G4LogicalVolume* mppcLogical =
1098 new G4LogicalVolume(mppcBox,
1099 Materials::get("G4_Si"),
1100 "BKLM.MPPCLogical"
1101 );
1102 m_VisAttributes.push_back(new G4VisAttributes(true));
1103 m_VisAttributes.back()->SetColour(1.0, 1.0, 1.0); // white
1104 mppcLogical->SetVisAttributes(m_VisAttributes.back());
1105 new G4PVPlacement(G4TranslateX3D(0.0),
1106 mppcLogical,
1107 "BKLM.MPPCPhysical",
1109 false,
1110 1,
1111 false
1112 );
1113 }
1114 return m_MPPCHousingLogical;
1115}
double getMPPCHousingRadius(void) const
Get the MPPC housing radius.
Definition: GeometryPar.h:541
double getMPPCHousingHalfLength(void) const
Get the MPPC housing half-length.
Definition: GeometryPar.h:547
double getMPPCHalfLength(void) const
Get the MPPC half-length.
Definition: GeometryPar.h:553
double getMPPCHalfWidth(void) const
Get the MPPC half-width.
Definition: GeometryPar.h:559
double getMPPCHalfHeight(void) const
Get the MPPC half-height.
Definition: GeometryPar.h:565

◆ getReadoutContainerLogical()

G4LogicalVolume * getReadoutContainerLogical ( void  )
private

Get pointer to readout-container logical volume.

Definition at line 1117 of file GeoBKLMCreator.cc.

1118{
1119 if (m_ReadoutContainerLogical == nullptr) {
1120 const CLHEP::Hep3Vector containerHalfSize = m_GeoPar->getReadoutContainerHalfSize() * CLHEP::cm;
1121 G4Box* containerBox =
1122 new G4Box("BKLM.ReadoutContainerSolid",
1123 containerHalfSize.x(), containerHalfSize.y(), containerHalfSize.z()
1124 );
1126 new G4LogicalVolume(containerBox,
1127 Materials::get("G4_AIR"),
1128 logicalName(containerBox)
1129 );
1130 m_ReadoutContainerLogical->SetVisAttributes(m_VisAttributes.front()); // invisible
1131
1132 const CLHEP::Hep3Vector carrierHalfSize = m_GeoPar->getReadoutCarrierHalfSize() * CLHEP::cm;
1133 G4Box* carrierBox =
1134 new G4Box("BKLM.ReadoutCarrierSolid",
1135 carrierHalfSize.x(), carrierHalfSize.y(), carrierHalfSize.z()
1136 );
1137 G4LogicalVolume* carrierLogical =
1138 new G4LogicalVolume(carrierBox,
1139 Materials::get("NEMA_G10_Plate"), // defined in CDC
1140 logicalName(carrierBox)
1141 );
1142 m_VisAttributes.push_back(new G4VisAttributes(true));
1143 m_VisAttributes.back()->SetColour(0.0, 1.0, 0.0);
1144 carrierLogical->SetVisAttributes(m_VisAttributes.back());
1145 const CLHEP::Hep3Vector preamplifierHalfSize = m_GeoPar->getReadoutPreamplifierHalfSize() * CLHEP::cm;
1146 G4Box* preamplifierBox =
1147 new G4Box("BKLM.ReadoutPreamplifierSolid",
1148 preamplifierHalfSize.x(), preamplifierHalfSize.y(), preamplifierHalfSize.z()
1149 );
1150 G4LogicalVolume* preamplifierLogical =
1151 new G4LogicalVolume(preamplifierBox,
1152 Materials::get("NEMA_G10_Plate"), // defined in CDC
1153 logicalName(preamplifierBox)
1154 );
1155 preamplifierLogical->SetVisAttributes(m_VisAttributes.back());
1156 const CLHEP::Hep3Vector connectorsHalfSize = m_GeoPar->getReadoutConnectorsHalfSize() * CLHEP::cm;
1157 G4Box* connectorsBox =
1158 new G4Box("BKLM.ReadoutConnectorsSolid",
1159 connectorsHalfSize.x(), connectorsHalfSize.y(), connectorsHalfSize.z()
1160 );
1161 G4LogicalVolume* connectorsLogical =
1162 new G4LogicalVolume(connectorsBox,
1163 Materials::get("G4_POLYCARBONATE"),
1164 logicalName(connectorsBox)
1165 );
1166 m_VisAttributes.push_back(new G4VisAttributes(true));
1167 m_VisAttributes.back()->SetColour(0.5, 0.5, 0.5);
1168 connectorsLogical->SetVisAttributes(m_VisAttributes.back());
1169 new G4PVPlacement(G4TranslateZ3D(preamplifierHalfSize.z()),
1170 carrierLogical,
1171 physicalName(carrierLogical),
1173 false,
1174 1,
1175 false
1176 );
1177 new G4PVPlacement(G4Translate3D(0.0, m_GeoPar->getReadoutConnectorsPosition(), -carrierHalfSize.z()),
1178 connectorsLogical,
1179 physicalName(connectorsLogical),
1181 false,
1182 1,
1183 false
1184 );
1185 for (int preamp = 1; preamp <= m_GeoPar->getNReadoutPreamplifierPosition(); ++preamp) {
1186 new G4PVPlacement(G4Translate3D(0.0,
1187 m_GeoPar->getReadoutPreamplifierPosition(preamp) * CLHEP::cm,
1188 -carrierHalfSize.z()),
1189 preamplifierLogical,
1190 physicalName(preamplifierLogical),
1192 false,
1193 1,
1194 false
1195 );
1196 }
1197 }
1199}
G4String logicalName(G4VSolid *)
convert G4VSolid's name to corresponding G4LogicalVolume name
G4String physicalName(G4LogicalVolume *)
convert G4LogicalVolume's name to corresponding G4PhysicalVolume name
const CLHEP::Hep3Vector getReadoutContainerHalfSize(void) const
Get the size (dx,dy,dz) of the readout container.
Definition: GeometryPar.cc:682
int getNReadoutPreamplifierPosition(void) const
Get the number of preamplifier positions along the length of the carrier card.
Definition: GeometryPar.h:520
double getReadoutConnectorsPosition(void) const
Get the position of the readout connectors pair along the length of the carrier card.
Definition: GeometryPar.h:535
const CLHEP::Hep3Vector getReadoutPreamplifierHalfSize(void) const
Get the size (dx,dy,dz) of the preamplifier card.
Definition: GeometryPar.cc:698
const CLHEP::Hep3Vector getReadoutConnectorsHalfSize(void) const
Get the size (dx,dy,dz) of the readout connectors pair.
Definition: GeometryPar.cc:706
double getReadoutPreamplifierPosition(int preamp) const
Get the position of a preamplifier along the length of the carrier card.
Definition: GeometryPar.h:526
const CLHEP::Hep3Vector getReadoutCarrierHalfSize(void) const
Get the size (dx,dy,dz) of the carrier card.
Definition: GeometryPar.cc:690

◆ getScintLogical()

G4LogicalVolume * getScintLogical ( double  dx,
double  dy,
double  dz,
double  dzMPPC 
)
private

Get pointer to scintillator logical volume.

Definition at line 986 of file GeoBKLMCreator.cc.

987{
988
989 int newLvol = 1;
990 for (std::vector<G4LogicalVolume*>::iterator iLvol = m_ScintLogicals.begin(); iLvol != m_ScintLogicals.end(); ++iLvol) {
991 G4Box* box = (G4Box*)((*iLvol)->GetSolid());
992 if ((std::fabs(box->GetXHalfLength() - dx) < 1.0E-4 * CLHEP::cm) &&
993 (std::fabs(box->GetYHalfLength() - dy) < 1.0E-4 * CLHEP::cm) &&
994 (std::fabs(box->GetZHalfLength() - dz - dzMPPC) < 1.0E-4 * CLHEP::cm)) { return *iLvol; }
995 newLvol++;
996 }
997 char name[80] = "";
998 sprintf(name, "BKLM.ScintType%dSolid", newLvol);
999 G4Box* scintBox = new G4Box(name, dx, dy, dz + dzMPPC);
1000 G4LogicalVolume* scintLogical =
1001 new G4LogicalVolume(scintBox, Materials::get("G4_POLYSTYRENE"), logicalName(scintBox));
1002 m_ScintLogicals.push_back(scintLogical);
1003 scintLogical->SetVisAttributes(m_VisAttributes.front()); // invisible
1004 sprintf(name, "BKLM.ScintType%dAirSolid", newLvol);
1005 G4Box* scintAirBox = new G4Box(name, dx, dy, dzMPPC);
1006 G4LogicalVolume* scintAirLogical =
1007 new G4LogicalVolume(scintAirBox, Materials::get("G4_AIR"), logicalName(scintAirBox));
1008 scintAirLogical->SetVisAttributes(m_VisAttributes.front()); // invisible
1009 double dxTiO2 = m_GeoPar->getScintTiO2ThicknessTop() * CLHEP::cm;
1010 double dyTiO2 = m_GeoPar->getScintTiO2ThicknessSide() * CLHEP::cm;
1011 sprintf(name, "BKLM.ScintActiveType%dSolid", newLvol);
1012 G4Box* activeBox = new G4Box(name, dx - dxTiO2, dy - dyTiO2, dz);
1013 G4LogicalVolume* activeLogical =
1014 new G4LogicalVolume(activeBox, Materials::get("G4_POLYSTYRENE"), logicalName(activeBox), 0, m_Sensitive, 0);
1015 m_VisAttributes.push_back(new G4VisAttributes(true));
1016 m_VisAttributes.back()->SetColour(1.0, 0.5, 0.0);
1017 activeLogical->SetVisAttributes(m_VisAttributes.back());
1018 sprintf(name, "BKLM.ScintBoreType%dSolid", newLvol);
1019 G4Tubs* boreTube = new G4Tubs(name, 0.0, m_GeoPar->getScintBoreRadius() * CLHEP::cm, dz, 0.0, 2.0 * M_PI);
1020 G4LogicalVolume* scintBoreLogical =
1021 new G4LogicalVolume(boreTube, Materials::get("G4_AIR"), logicalName(boreTube));
1022 scintBoreLogical->SetVisAttributes(m_VisAttributes.front()); // invisible
1023 sprintf(name, "BKLM.ScintFiberType%dSolid", newLvol);
1024 G4Tubs* fiberTube = new G4Tubs(name, 0.0, m_GeoPar->getScintFiberRadius() * CLHEP::cm, dz, 0.0, 2.0 * M_PI);
1025 G4LogicalVolume* scintFiberLogical = new G4LogicalVolume(fiberTube, Materials::get("G4_POLYSTYRENE"), logicalName(fiberTube));
1026 m_VisAttributes.push_back(new G4VisAttributes(true));
1027 m_VisAttributes.back()->SetColour(0.0, 1.0, 0.0);
1028 scintFiberLogical->SetVisAttributes(m_VisAttributes.back());
1029 new G4PVPlacement(G4TranslateZ3D(0.0),
1030 scintFiberLogical,
1031 physicalName(scintFiberLogical),
1032 scintBoreLogical,
1033 false,
1034 1,
1035 false
1036 );
1037 new G4PVPlacement(G4TranslateZ3D(0.0),
1038 scintBoreLogical,
1039 physicalName(scintBoreLogical),
1040 activeLogical,
1041 false,
1042 1,
1043 false
1044 );
1045 new G4PVPlacement(G4TranslateZ3D(-dzMPPC),
1046 activeLogical,
1047 physicalName(activeLogical),
1048 scintLogical,
1049 false,
1050 1,
1051 false
1052 );
1053 new G4PVPlacement(G4TranslateZ3D(0.0),
1055 "BKLM.MPPCHousingPhysical",
1056 scintAirLogical,
1057 false,
1058 1,
1059 false
1060 );
1061 new G4PVPlacement(G4TranslateZ3D(dz),
1062 scintAirLogical,
1063 physicalName(scintAirLogical),
1064 scintLogical,
1065 false,
1066 1,
1067 false
1068 );
1069 return scintLogical;
1070}
G4LogicalVolume * getMPPCHousingLogical(void)
Get pointer to MPPC-container logical volume.
double getScintBoreRadius(void) const
Get the radius of the cylindrical central bore in a scintillator strip.
Definition: GeometryPar.h:124
double getScintTiO2ThicknessTop(void) const
Get the thickness of the inactive TiO2-polystyrene coating on top (broad) surface of a scintillator s...
Definition: GeometryPar.h:100
double getScintFiberRadius(void) const
Get the radius of the cylindrical central WLS fiber in a scintillator strip.
Definition: GeometryPar.h:130
double getScintTiO2ThicknessSide(void) const
Get the thickness of the inactive TiO2-polystyrene coating on side (short) surface of a scintillator ...
Definition: GeometryPar.h:106

◆ getSolenoidTube()

G4Tubs * getSolenoidTube ( void  )
private

Get shape corresponding to the solenoid (for subtraction)

Definition at line 1201 of file GeoBKLMCreator.cc.

1202{
1203
1204 if (m_SolenoidTube == nullptr) {
1206 new G4Tubs("BKLM.SolenoidTube",
1207 0.0,
1208 m_GeoPar->getSolenoidOuterRadius() * CLHEP::cm,
1209 2.0 * m_GeoPar->getHalfLength() * CLHEP::cm,
1210 0.0,
1211 2.0 * M_PI
1212 );
1213 }
1214 return m_SolenoidTube;
1215}

◆ logicalName()

G4String logicalName ( G4VSolid *  solid)
private

convert G4VSolid's name to corresponding G4LogicalVolume name

Definition at line 1217 of file GeoBKLMCreator.cc.

1218{
1219 G4String* name = new G4String(solid->GetName().substr(0, solid->GetName().size() - 5) + "Logical");
1220 m_Names.push_back(name);
1221 return *name;
1222}

◆ physicalName()

G4String physicalName ( G4LogicalVolume *  lvol)
private

convert G4LogicalVolume's name to corresponding G4PhysicalVolume name

Definition at line 1224 of file GeoBKLMCreator.cc.

1225{
1226 G4String* name = new G4String(lvol->GetName().substr(0, lvol->GetName().size() - 7) + "Physical");
1227 m_Names.push_back(name);
1228 return *name;
1229}

◆ putCapInSector()

void putCapInSector ( G4LogicalVolume *  sectorLogical,
bool  hasChimney 
)
private

Put the cap (at maximum |z|) into each sector.

Definition at line 216 of file GeoBKLMCreator.cc.

217{
218
219 // Fill cap with iron and (aluminum) cables
220 const CLHEP::Hep3Vector gapHalfSize = m_GeoPar->getGapHalfSize(0, false) * CLHEP::cm;
221 const double dyBrace = (hasChimney ? m_GeoPar->getBraceWidthChimney() : m_GeoPar->getBraceWidth()) * CLHEP::cm;
222 const double dy = 0.25 * (m_GeoPar->getCablesWidth() * CLHEP::cm - dyBrace);
223 const double dz = m_SectorDz - gapHalfSize.z();
224 const double ri = m_GeoPar->getLayerInnerRadius(1) * CLHEP::cm + 2.0 * gapHalfSize.x();
225 const double ro = m_GeoPar->getOuterRadius() * CLHEP::cm;
226 if (m_CapSolid == nullptr) {
227 const double z[2] = { -dz, dz};
228 const double rInner[2] = {ri, ri};
229 const double rOuter[2] = {ro, ro};
230 m_CapSolid =
231 new G4Polyhedra("BKLM.CapSolid",
232 -0.5 * m_SectorDphi,
234 1,
235 2, z, rInner, rOuter
236 );
237 }
238 int newLvol = (hasChimney ? 1 : 0);
239 G4String name = (hasChimney ? "BKLM.ChimneyCapLogical" : "BKLM.CapLogical");
240 if (m_CapLogical[newLvol] == nullptr) {
241 m_CapLogical[newLvol] =
242 new G4LogicalVolume(m_CapSolid,
243 Materials::get("G4_Fe"),
244 name
245 );
246 m_CapLogical[newLvol]->SetVisAttributes(m_VisAttributes.front()); // invisible
247 name = (hasChimney ? "BKLM.ChimneyCablesSolid" : "BKLM.CablesSolid");
248 G4Box* cablesSolid =
249 new G4Box(name, 0.5 * (ro - ri), dy, dz);
250 G4LogicalVolume* cablesLogical =
251 new G4LogicalVolume(cablesSolid,
252 Materials::get("G4_Al"),
253 logicalName(cablesSolid)
254 );
255 cablesLogical->SetVisAttributes(m_VisAttributes.front()); // invisible
256 new G4PVPlacement(G4Translate3D(0.5 * (ri + ro), -(0.5 * dyBrace + dy), 0.0),
257 cablesLogical,
258 physicalName(cablesLogical).append(G4String("_L")),
259 m_CapLogical[newLvol],
260 false,
261 1,
262 false
263 );
264 new G4PVPlacement(G4Translate3D(0.5 * (ri + ro), +(0.5 * dyBrace + dy), 0.0),
265 cablesLogical,
266 physicalName(cablesLogical).append(G4String("_R")),
267 m_CapLogical[newLvol],
268 false,
269 2,
270 false
271 );
272 }
273 new G4PVPlacement(G4TranslateZ3D(m_SectorDz - dz),
274 m_CapLogical[newLvol],
275 physicalName(m_CapLogical[newLvol]),
276 sectorLogical,
277 false,
278 1,
279 false
280 );
281}
const CLHEP::Hep3Vector getGapHalfSize(int layer, bool hasChimney) const
Get the size (dx,dy,dz) of the gap [=slot] of specified layer.
Definition: GeometryPar.cc:505
double getBraceWidthChimney(void) const
Get the width of the brace in the middle of the cable-services channel in the chimney sector.
Definition: GeometryPar.h:439
double getCablesWidth(void) const
Get the width of the cable-services channel at each end.
Definition: GeometryPar.h:427
double getBraceWidth(void) const
Get the width of the brace in the middle of the cable-services channel.
Definition: GeometryPar.h:433
double getLayerInnerRadius(int layer) const
Get the inner radius of specified layer.
Definition: GeometryPar.cc:489

◆ putChimneyInLayer()

void putChimneyInLayer ( G4LogicalVolume *  layerIronLogical,
int  layer 
)
private

Put the solenoid's cooling chimney into the backward top sector.

Definition at line 560 of file GeoBKLMCreator.cc.

561{
562 CLHEP::Hep3Vector gapHalfSize = m_GeoPar->getGapHalfSize(layer, true) * CLHEP::cm;
563 CLHEP::Hep3Vector chimneyHalfSize = m_GeoPar->getChimneyHalfSize(layer) * CLHEP::cm;
564 CLHEP::Hep3Vector chimneyPosition = m_GeoPar->getChimneyPosition(layer) * CLHEP::cm;
565 gapHalfSize.setY(0.5 * (gapHalfSize.y() - chimneyHalfSize.y()));
566 gapHalfSize.setZ(chimneyHalfSize.z() + 0.5 * m_GeoPar->getChimneyCoverThickness() * CLHEP::cm);
567 double dx = m_GeoPar->getGapMiddleRadius(layer) * CLHEP::cm;
568 double dy = gapHalfSize.y() + chimneyHalfSize.y();
569 double dz = 0.5 * m_GeoPar->getGapLength() * CLHEP::cm - gapHalfSize.z();
570 char name[80] = "";
571 // Fill the two chimney gaps with air
572 sprintf(name, "BKLM.Layer%02dGapChimneyBox", layer);
573 G4Box* gapBox =
574 new G4Box(name,
575 gapHalfSize.x(), gapHalfSize.y(), gapHalfSize.z()
576 );
577 sprintf(name, "BKLM.Layer%02dGapChimneyLogical", layer);
578 G4LogicalVolume* gapLogical =
579 new G4LogicalVolume(gapBox,
580 Materials::get("G4_AIR"),
581 name
582 );
583 gapLogical->SetVisAttributes(m_VisAttributes.front()); // invisible
584 sprintf(name, "BKLM.Layer%02dLeftGapChimneyPhysical", layer);
585 new G4PVPlacement(G4Translate3D(dx, -dy, dz),
586 gapLogical,
587 name,
588 layerIronLogical,
589 false,
590 0,
591 false
592 );
593 sprintf(name, "BKLM.Layer%02dRightGapChimneyPhysical", layer);
594 new G4PVPlacement(G4Translate3D(dx, +dy, dz),
595 gapLogical,
596 name,
597 layerIronLogical,
598 false,
599 1,
600 false
601 );
602 // Fill chimney with air
603 sprintf(name, "BKLM.Layer%02dChimneyBox", layer);
604 G4Box* chimneyBox =
605 new G4Box(name,
606 chimneyHalfSize.x(), chimneyHalfSize.y(), chimneyHalfSize.z()
607 );
608 sprintf(name, "BKLM.Layer%02dChimneyLogical", layer);
609 G4LogicalVolume* chimneyLogical =
610 new G4LogicalVolume(chimneyBox,
611 Materials::get("G4_AIR"),
612 name
613 );
614 chimneyLogical->SetVisAttributes(m_VisAttributes.front()); // invisible
615 // Place coaxial tubes in chimney
616 G4Tubs* housingTube =
617 new G4Tubs("BKLM.ChimneyHousingTube",
620 chimneyHalfSize.x(),
621 0.0,
622 2.0 * M_PI
623 );
624 G4LogicalVolume* housingLogical =
625 new G4LogicalVolume(housingTube,
626 Materials::get("G4_Fe"),
627 "BKLM.ChimneyHousingLogical"
628 );
629 m_VisAttributes.push_back(new G4VisAttributes(true));
630 m_VisAttributes.back()->SetColour(0.4, 0.4, 0.4);
631 housingLogical->SetVisAttributes(m_VisAttributes.back());
632 new G4PVPlacement(G4RotateY3D(M_PI_2),
633 housingLogical,
634 "BKLM.ChimneyHousingPhysical",
635 chimneyLogical,
636 false,
637 0,
638 false
639 );
640 G4Tubs* shieldTube =
641 new G4Tubs("BKLM.ChimneyShieldTube",
644 chimneyHalfSize.x(),
645 0.0,
646 2.0 * M_PI
647 );
648 G4LogicalVolume* shieldLogical =
649 new G4LogicalVolume(shieldTube,
650 Materials::get("G4_Fe"),
651 "BKLM.ChimneyShieldLogical"
652 );
653 shieldLogical->SetVisAttributes(m_VisAttributes.back());
654 new G4PVPlacement(G4RotateY3D(M_PI_2),
655 shieldLogical,
656 "BKLM.ChimneyShieldPhysical",
657 chimneyLogical,
658 false,
659 0,
660 false
661 );
662 G4Tubs* pipeTube =
663 new G4Tubs("BKLM.ChimneyPipeTube",
664 m_GeoPar->getChimneyPipeInnerRadius() * CLHEP::cm,
665 m_GeoPar->getChimneyPipeOuterRadius() * CLHEP::cm,
666 chimneyHalfSize.x(),
667 0.0,
668 2.0 * M_PI
669 );
670 G4LogicalVolume* pipeLogical =
671 new G4LogicalVolume(pipeTube,
672 Materials::get("G4_Fe"),
673 "BKLM.ChimneyPipeLogical"
674 );
675 m_VisAttributes.push_back(new G4VisAttributes(true));
676 m_VisAttributes.back()->SetColour(0.6, 0.6, 0.6);
677 pipeLogical->SetVisAttributes(m_VisAttributes.back());
678 new G4PVPlacement(G4RotateY3D(M_PI_2),
679 pipeLogical,
680 "BKLM.ChimneyPipePhysical",
681 chimneyLogical,
682 false,
683 0,
684 false
685 );
686 sprintf(name, "BKLM.Layer%02dChimneyPhysical", layer);
687 new G4PVPlacement(G4Translate3D(chimneyPosition),
688 chimneyLogical,
689 name,
690 layerIronLogical,
691 false,
692 0,
693 false
694 );
695}
double getChimneyShieldInnerRadius(void) const
Get the inner radius of the chimney radiation shield.
Definition: GeometryPar.h:397
const CLHEP::Hep3Vector getChimneyPosition(int layer) const
Get the position of the chimney hole in the specified layer.
Definition: GeometryPar.cc:650
double getChimneyPipeOuterRadius(void) const
Get the outer radius of the chimney pipe.
Definition: GeometryPar.h:415
double getChimneyHousingInnerRadius(void) const
Get the inner radius of the chimney housing.
Definition: GeometryPar.h:385
const CLHEP::Hep3Vector getChimneyHalfSize(int layer) const
Get the size of the chimney hole in the specified layer.
Definition: GeometryPar.cc:643
double getGapMiddleRadius(int layer) const
Get the radial midpoint of the gap of specified layer.
Definition: GeometryPar.cc:591
double getChimneyShieldOuterRadius(void) const
Get the outer radius of the chimney radiation shield.
Definition: GeometryPar.h:403
double getChimneyCoverThickness(void) const
Get the thickness of the chimney cover plate.
Definition: GeometryPar.h:379
double getGapLength(void) const
Get the length along z of the module gap.
Definition: GeometryPar.h:235
double getChimneyPipeInnerRadius(void) const
Get the inner radius of the chimney pipe.
Definition: GeometryPar.h:409
double getChimneyHousingOuterRadius(void) const
Get the outer radius of the chimney housing.
Definition: GeometryPar.h:391

◆ putEndsInEnvelope()

void putEndsInEnvelope ( G4LogicalVolume *  envelopeLogical)
private

Put the forward and backward ends into the BKLM envelope.

Definition at line 135 of file GeoBKLMCreator.cc.

136{
137 G4Tubs* endSolid =
138 new G4Tubs("BKLM.EndSolid",
139 m_GeoPar->getSolenoidOuterRadius() * CLHEP::cm,
140 m_GeoPar->getOuterRadius() * CLHEP::cm / cos(0.5 * m_SectorDphi),
142 0.0,
143 2.0 * M_PI
144 );
145 G4LogicalVolume* frontLogical =
146 new G4LogicalVolume(endSolid,
147 Materials::get("G4_AIR"),
148 "BKLM.F_Logical"
149 );
150 frontLogical->SetVisAttributes(m_VisAttributes.front()); // invisible
152 new G4PVPlacement(G4TranslateZ3D(m_SectorDz),
153 frontLogical,
154 "BKLM.F_Physical",
155 envelopeLogical,
156 false,
158 false
159 );
160 G4LogicalVolume* backLogical =
161 new G4LogicalVolume(endSolid,
162 Materials::get("G4_AIR"),
163 "BKLM.B_Logical"
164 );
165 backLogical->SetVisAttributes(m_VisAttributes.front()); // invisible
167 new G4PVPlacement(G4TranslateZ3D(-m_SectorDz) * G4RotateY3D(M_PI),
168 backLogical,
169 "BKLM.B_Physical",
170 envelopeLogical,
171 false,
173 false
174 );
175
176}
void putSectorsInEnd(G4LogicalVolume *, int)
Put each sector into the forward or backward end.

◆ putInnerRegionInSector()

void putInnerRegionInSector ( G4LogicalVolume *  sectorLogical,
bool  hasInnerSupport,
bool  hasChimney 
)
private

Put the inner-radius region into each sector.

Definition at line 283 of file GeoBKLMCreator.cc.

284{
285
286 // Fill inner region with iron
287 if (m_InnerIronSolid == nullptr) {
288 const double r = m_GeoPar->getLayerInnerRadius(1) * CLHEP::cm;
289 const double z[2] = { -m_SectorDz, +m_SectorDz};
290 const double rInner[2] = {0.0, 0.0};
291 const double rOuter[2] = {r, r};
292 G4Polyhedra* innerIronPolygon =
293 new G4Polyhedra("BKLM.InnerIronPolygon",
294 -0.5 * m_SectorDphi,
296 1,
297 2, z, rInner, rOuter
298 );
300 new G4SubtractionSolid("BKLM.InnerIronSolid",
301 innerIronPolygon,
303 );
304 }
305 int newLvol = (hasInnerSupport ? 2 : 0) + (hasChimney ? 1 : 0);
306 if (m_InnerIronLogical[newLvol] == nullptr) {
307 m_InnerIronLogical[newLvol] =
308 new G4LogicalVolume(m_InnerIronSolid,
309 Materials::get("G4_Fe"),
310 (hasChimney ? "BKLM.InnerIronChimneyLogical" : "BKLM.InnerIronLogical")
311 );
312 m_InnerIronLogical[newLvol]->SetVisAttributes(m_VisAttributes.front()); // invisible
313 putVoidInInnerRegion(m_InnerIronLogical[newLvol], hasInnerSupport, hasChimney);
314 }
315 new G4PVPlacement(G4TranslateZ3D(0.0),
316 m_InnerIronLogical[newLvol],
318 sectorLogical,
319 false,
320 1,
321 false
322 );
323}
G4Tubs * getSolenoidTube(void)
Get shape corresponding to the solenoid (for subtraction)
void putVoidInInnerRegion(G4LogicalVolume *, bool, bool)
Put the air void into the inner-radius region.

◆ putLayer1BracketsInInnerVoid()

void putLayer1BracketsInInnerVoid ( G4LogicalVolume *  innerAirLogical,
bool  hasChimney 
)
private

Put the layer-0 support plate's brackets into the inner region's air void (sectors 1..5 only)

Definition at line 403 of file GeoBKLMCreator.cc.

404{
405
406 if (m_BracketLogical == nullptr) {
407 const CLHEP::Hep3Vector size = m_GeoPar->getSupportPlateHalfSize(hasChimney) * CLHEP::cm;
408 const double dz = 0.5 * m_GeoPar->getBracketLength() * CLHEP::cm;
409 const double r = m_GeoPar->getLayerInnerRadius(1) * CLHEP::cm - m_RibShift - 2.0 * size.x();
410 const double bracketShift = m_GeoPar->getBracketRibThickness() * CLHEP::cm / sin(0.5 * m_SectorDphi);
411 const double z[2] = { -dz, +dz};
412 const double rInner[2] = {0.0, 0.0};
413 const double rOuter[2] = {r, r};
414 const double r1 = m_GeoPar->getBracketInnerRadius() * CLHEP::cm - m_RibShift;
415 const double z1[2] = { -(dz + 0.5 * CLHEP::cm), dz + 0.5 * CLHEP::cm};
416 const double rOuter1[2] = {r1, r1};
417 const double z2[2] = { -(dz + 1.0 * CLHEP::cm), dz + 1.0 * CLHEP::cm};
418 const double dzBracket = m_GeoPar->getBracketThickness() * CLHEP::cm;
419 const double drBracket = dzBracket + bracketShift;
420 const double rOuter2[2] = {r - drBracket, r - drBracket};
421 const double z3[2] = { -dzBracket, dzBracket};
422 const double cutoutDphi = m_GeoPar->getBracketCutoutDphi() * CLHEP::rad;
423 G4Polyhedra* bracketPolygon =
424 new G4Polyhedra("BKLM.BracketPolygon",
425 -0.5 * m_SectorDphi,
427 1,
428 2, z, rInner, rOuter
429 );
430 G4Polyhedra* bracketCutout1 =
431 new G4Polyhedra("BKLM.BracketCutout1",
432 -0.5 * cutoutDphi,
433 cutoutDphi,
434 2, // two sides
435 2, z1, rInner, rOuter1
436 );
437 G4Polyhedra* bracketCutout2 =
438 new G4Polyhedra("BKLM.BracketCutout2",
439 -0.5 * m_SectorDphi,
441 1,
442 2, z2, rInner, rOuter2
443 );
444 G4Polyhedra* bracketCutout3 =
445 new G4Polyhedra("BKLM.BracketCutout3",
446 -0.5 * m_SectorDphi,
448 1,
449 2, z3, rInner, rOuter2
450 );
451 G4Box* bracketCutout4 =
452 new G4Box("BKLM.BracketCutout4",
453 rOuter[1] + 1.0 * CLHEP::cm,
454 rOuter[1] * tan(0.5 * m_SectorDphi) - m_GeoPar->getBracketWidth() * CLHEP::cm,
455 z[1] + 1.5 * CLHEP::cm
456 );
457 G4VSolid* polygon1 =
458 new G4SubtractionSolid("BKLM.BracketPolygon1",
459 bracketPolygon,
460 bracketCutout4
461 );
462 G4VSolid* polygon2 =
463 new G4SubtractionSolid("BKLM.BracketPolygon2",
464 bracketCutout2,
465 bracketCutout3
466 );
467 G4VSolid* polygon3 =
468 new G4SubtractionSolid("BKLM.BracketPolygon3",
469 polygon1,
470 polygon2,
471 G4TranslateX3D(bracketShift)
472 );
473 G4VSolid* bracketSolid =
474 new G4SubtractionSolid("BKLM.BracketSolid",
475 polygon3,
476 bracketCutout1
477 );
479 new G4LogicalVolume(bracketSolid,
480 Materials::get("G4_Al"),
481 "BKLM.BracketLogical"
482 );
483 m_VisAttributes.push_back(new G4VisAttributes(true));
484 m_VisAttributes.back()->SetColour(0.6, 0.6, 0.6);
485 m_BracketLogical->SetVisAttributes(m_VisAttributes.back());
486 }
487 char name[80] = "";
488 for (int bracket = 0; bracket < (hasChimney ? 2 : 3); ++bracket) {
489 sprintf(name, "BKLM.Bracket%d%sPhysical", bracket, (hasChimney ? "Chimney" : ""));
490 new G4PVPlacement(G4TranslateZ3D(m_GeoPar->getBracketZPosition(bracket, hasChimney) * CLHEP::cm),
492 name,
493 innerAirLogical,
494 false,
495 bracket,
496 false
497 );
498 }
499}
double getBracketThickness(void) const
Get the thickness of the layer-0 support plate's bracket.
Definition: GeometryPar.h:454
double getBracketWidth(void) const
Get the width of the layer-0 support plate's bracket.
Definition: GeometryPar.h:448
double getBracketZPosition(int, bool) const
Get the position of a layer-0 support plate's bracket.
Definition: GeometryPar.cc:670
double getBracketLength(void) const
Get the length of the layer-0 support plate's bracket.
Definition: GeometryPar.h:460
double getBracketRibThickness(void) const
Get the thickness of the layer-0 support plate's bracket's rib.
Definition: GeometryPar.h:472
const CLHEP::Hep3Vector getSupportPlateHalfSize(bool) const
Get the size of the layer-0 support plate.
Definition: GeometryPar.cc:657
double getBracketCutoutDphi(void) const
Get the angular width of the layer-0 support plate's bracket's cutout.
Definition: GeometryPar.h:487
double getBracketInnerRadius(void) const
Get the inner radius of the layer-0 support plate's bracket.
Definition: GeometryPar.h:478

◆ putLayer1SupportInInnerVoid()

void putLayer1SupportInInnerVoid ( G4LogicalVolume *  innerAirLogical,
bool  hasChimney 
)
private

Put the layer-0 support plate into the inner region's air void (sectors 1..5 only)

Definition at line 372 of file GeoBKLMCreator.cc.

373{
374
375 int newLvol = (hasChimney ? 1 : 0);
376 const CLHEP::Hep3Vector size = m_GeoPar->getSupportPlateHalfSize(hasChimney) * CLHEP::cm;
377 if (m_SupportLogical[newLvol] == nullptr) {
378 G4Box* supportBox =
379 new G4Box((hasChimney ? "BKLM.ChimneySupportSolid" : "BKLM.SupportSolid"),
380 size.x(),
381 size.y(),
382 size.z()
383 );
384 m_SupportLogical[newLvol] =
385 new G4LogicalVolume(supportBox,
386 Materials::get("G4_Al"),
387 logicalName(supportBox)
388 );
389 m_SupportLogical[newLvol]->SetVisAttributes(m_VisAttributes.front()); // invisible
390 }
391 double dx = m_GeoPar->getLayerInnerRadius(1) * CLHEP::cm - size.x() - m_RibShift;
392 double dz = size.z() - m_SectorDz;
393 new G4PVPlacement(G4Translate3D(dx, 0.0, dz),
394 m_SupportLogical[newLvol],
396 innerAirLogical,
397 false,
398 1,
399 false
400 );
401}

◆ putLayersInSector()

void putLayersInSector ( G4LogicalVolume *  sectorLogical,
int  section,
int  sector,
bool  hasChimney 
)
private

Put the layers into each sector.

Definition at line 501 of file GeoBKLMCreator.cc.

502{
503
504 const double dz = 0.5 * m_GeoPar->getGapLength() * CLHEP::cm;
505 const double z[2] = { -dz, +dz };
506 char name[80] = "";
507 for (int layer = 1; layer <= m_GeoPar->getNLayer(); ++layer) {
508 // Fill layer with iron
509 if (m_LayerIronSolid[layer - 1] == nullptr) {
510 const double ri = m_GeoPar->getLayerInnerRadius(layer) * CLHEP::cm;
511 const double ro = m_GeoPar->getLayerOuterRadius(layer) * CLHEP::cm;
512 const double rInner[2] = {ri, ri};
513 const double rOuter[2] = {ro, ro};
514 sprintf(name, "BKLM.Layer%02dIronSolid", layer);
515 m_LayerIronSolid[layer - 1] =
516 new G4Polyhedra(name,
517 -0.5 * m_SectorDphi,
519 1,
520 2, z, rInner, rOuter
521 );
522 }
523 const Module* module = m_GeoPar->findModule(section == BKLMElementNumbers::c_ForwardSection, sector, layer);
524 bool isFlipped = module->isFlipped();
525 int newLvol = BKLMElementNumbers::getMaximalLayerNumber() * ((isFlipped ? 2 : 0) +
526 (hasChimney ? 1 : 0)) + (layer - 1);
527 int s1 = sector - 1;
528 int s2 = m_GeoPar->getNSector() / 2;
529 if (s1 % s2 == 0) {
530 } else if (s1 > s2) {
532 } else {
534 }
535 if (m_LayerIronLogical[newLvol] == nullptr) {
536 sprintf(name, "BKLM.Layer%02d%s%sIronLogical", layer, (isFlipped ? "Flipped" : ""), (hasChimney ? "Chimney" : ""));
537 m_LayerIronLogical[newLvol] =
538 new G4LogicalVolume(m_LayerIronSolid[layer - 1],
539 Materials::get("G4_Fe"),
540 name
541 );
542 m_LayerIronLogical[newLvol]->SetVisAttributes(m_VisAttributes.front()); // invisible
543 putModuleInLayer(m_LayerIronLogical[newLvol], section, sector, layer, hasChimney, isFlipped, newLvol);
544 if (hasChimney) {
545 putChimneyInLayer(m_LayerIronLogical[newLvol], layer);
546 }
547 }
548 new G4PVPlacement(G4TranslateZ3D(dz - m_SectorDz),
549 m_LayerIronLogical[newLvol],
551 sectorLogical,
552 false,
553 layer,
554 false
555 );
556
557 }
558}
void putChimneyInLayer(G4LogicalVolume *, int)
Put the solenoid's cooling chimney into the backward top sector.
void putModuleInLayer(G4LogicalVolume *, int, int, int, bool, bool, int)
Put the module (and enclosing air gap) into each layer.
double getLayerOuterRadius(int layer) const
Get the outer radius of specified layer.
Definition: GeometryPar.cc:500
const Module * findModule(int section, int sector, int layer) const
Get the pointer to the definition of a module.
Definition: GeometryPar.cc:721
int getNLayer(void) const
Get the number of modules in one sector.
Definition: GeometryPar.h:193
Define the geometry of a BKLM module Each sector [octant] contains Modules.
Definition: Module.h:76

◆ putModuleInLayer()

void putModuleInLayer ( G4LogicalVolume *  layerIronLogical,
int  section,
int  sector,
int  layer,
bool  hasChimney,
bool  isFlipped,
int  newLvol 
)
private

Put the module (and enclosing air gap) into each layer.

Definition at line 697 of file GeoBKLMCreator.cc.

699{
700 const CLHEP::Hep3Vector gapHalfSize = m_GeoPar->getGapHalfSize(layer, hasChimney) * CLHEP::cm;
701 const CLHEP::Hep3Vector moduleHalfSize = m_GeoPar->getModuleHalfSize(layer, hasChimney) * CLHEP::cm;
702 char name[80] = "";
703 // Fill gap with air
704 int modLvol = (hasChimney ? BKLMElementNumbers::getMaximalLayerNumber() : 0) + (layer - 1);
705 if (m_LayerModuleLogical[modLvol] == nullptr) {
706 // Module is aluminum (but interior will be filled)
707 sprintf(name, "BKLM.Layer%02d%sModuleSolid", layer, (hasChimney ? "Chimney" : ""));
708 G4Box* moduleBox =
709 new G4Box(name,
710 moduleHalfSize.x(), moduleHalfSize.y(), moduleHalfSize.z()
711 );
712 m_LayerModuleLogical[modLvol] =
713 new G4LogicalVolume(moduleBox,
714 Materials::get("G4_Al"),
715 logicalName(moduleBox)
716 );
717 m_LayerModuleLogical[modLvol]->SetVisAttributes(m_VisAttributes.front()); // invisible
718 sprintf(name, "BKLM.Layer%02d%sModuleInteriorSolid1", layer, (hasChimney ? "Chimney" : ""));
719 const CLHEP::Hep3Vector interiorHalfSize1 = m_GeoPar->getModuleInteriorHalfSize1(layer, hasChimney) * CLHEP::cm;
720 G4Box* interiorBox1 =
721 new G4Box(name,
722 interiorHalfSize1.x(), interiorHalfSize1.y(), interiorHalfSize1.z()
723 );
724 sprintf(name, "BKLM.Layer%02d%sModuleInteriorSolid2", layer, (hasChimney ? "Chimney" : ""));
725 const CLHEP::Hep3Vector interiorHalfSize2 = m_GeoPar->getModuleInteriorHalfSize2(layer, hasChimney) * CLHEP::cm;
726 G4Box* interiorBox2 =
727 new G4Box(name,
728 interiorHalfSize2.x(), interiorHalfSize2.y(), interiorHalfSize2.z()
729 );
730 sprintf(name, "BKLM.Layer%02d%sModuleInteriorSolid", layer, (hasChimney ? "Chimney" : ""));
731 G4UnionSolid* interiorUnion =
732 new G4UnionSolid(name, interiorBox1, interiorBox2);
733 G4LogicalVolume* interiorLogical =
734 new G4LogicalVolume(interiorUnion,
735 Materials::get((m_GeoPar->hasRPCs(layer) ? "RPCReadout" : "G4_POLYSTYRENE")),
736 logicalName(interiorUnion)
737 );
738 interiorLogical->SetVisAttributes(m_VisAttributes.front()); // invisible
739 if (m_GeoPar->hasRPCs(layer)) {
740 putRPCsInInterior(interiorLogical, layer, hasChimney);
741 } else {
742 putScintsInInterior(interiorLogical, section, sector, layer, hasChimney);
743 }
744 new G4PVPlacement(G4TranslateZ3D(0.0),
745 interiorLogical,
746 physicalName(interiorLogical),
747 m_LayerModuleLogical[modLvol],
748 false,
749 0,
750 false
751 );
752 sprintf(name, "BKLM.Layer%02d%sGapSolid", layer, (hasChimney ? "Chimney" : ""));
753 m_LayerGapSolid[modLvol] =
754 new G4Box(name,
755 gapHalfSize.x(), gapHalfSize.y(), gapHalfSize.z()
756 );
757 }
758 if (m_LayerGapLogical[newLvol] == nullptr) {
759 sprintf(name, "BKLM.Layer%02d%s%sGapLogical", layer, (isFlipped ? "Flipped" : ""), (hasChimney ? "Chimney" : ""));
760 m_LayerGapLogical[newLvol] =
761 new G4LogicalVolume(m_LayerGapSolid[modLvol],
762 Materials::get("G4_AIR"),
763 name
764 );
765 m_LayerGapLogical[newLvol]->SetVisAttributes(m_VisAttributes.front()); // invisible
766 }
767 double dx = (m_GeoPar->getModuleMiddleRadius(layer) - m_GeoPar->getGapMiddleRadius(layer)) * CLHEP::cm;
768 // Module is closer to IP within gap if in the upper octants, farther from IP within gap if in the lower octants,
769 // or in the middle of the gap if in the side octants.
770 int s1 = sector - 1;
771 int s2 = m_GeoPar->getNSector() / 2;
772 if (s1 % s2 == 0) {
773 dx = 0.0;
774 } else if (s1 > s2) {
775 dx = -dx;
776 }
777 double dz = moduleHalfSize.z() - gapHalfSize.z();
778 G4Transform3D displacedGeo = m_GeoPar->getModuleDisplacedGeo(section == BKLMElementNumbers::c_ForwardSection, sector, layer);
779 new G4PVPlacement(G4Translate3D(dx, 0.0, dz) * G4RotateZ3D(isFlipped ? M_PI : 0.0) * displacedGeo,
780 m_LayerModuleLogical[modLvol],
782 m_LayerGapLogical[newLvol],
783 false,
784 0,
785 false
786 );
787 dz = gapHalfSize.z() - 0.5 * m_GeoPar->getGapLength() * CLHEP::cm;
788 new G4PVPlacement(G4Translate3D(m_GeoPar->getGapMiddleRadius(layer) * CLHEP::cm, 0.0, dz),
789 m_LayerGapLogical[newLvol],
791 layerIronLogical,
792 false,
793 layer,
794 false
795 );
796}
void putScintsInInterior(G4LogicalVolume *, int, int, int, bool)
Put the scintillators into each detector module's interior (module is itself in an air gap)
void putRPCsInInterior(G4LogicalVolume *, int, bool)
Put the RPCs into each detector module's interior (module is itself in an air gap)
const CLHEP::Hep3Vector getModuleHalfSize(int layer, bool hasChimney) const
Get the size (dx,dy,dz) of the detector module of specified layer.
Definition: GeometryPar.cc:522
const CLHEP::Hep3Vector getModuleInteriorHalfSize1(int layer, bool hasChimney) const
Get the size (dx,dy,dz) of the detector module's interior volume 1.
Definition: GeometryPar.cc:530
bool hasRPCs(int layer) const
Determine if the sensitive detectors in a given layer are RPCs (=true) or scintillators (=false)
Definition: GeometryPar.cc:714
const CLHEP::Hep3Vector getModuleInteriorHalfSize2(int layer, bool hasChimney) const
Get the size (dx,dy,dz) of the scintillator detector module's polystyrene filler.
Definition: GeometryPar.cc:539
double getModuleMiddleRadius(int layer) const
Get the radial midpoint of the detector module of specified layer.
Definition: GeometryPar.cc:599
const HepGeom::Transform3D getModuleDisplacedGeo(int section, int sector, int layer) const
Get the displacement transformation of a module.
Definition: GeometryPar.cc:735

◆ putRPCsInInterior()

void putRPCsInInterior ( G4LogicalVolume *  interiorLogical,
int  layer,
bool  hasChimney 
)
private

Put the RPCs into each detector module's interior (module is itself in an air gap)

Definition at line 798 of file GeoBKLMCreator.cc.

799{
800 char name[80] = "";
801 // Place electrode inside the module's interior
802 sprintf(name, "BKLM.Layer%02d%sElectrodeSolid", layer, (hasChimney ? "Chimney" : ""));
803 const CLHEP::Hep3Vector electrodeHalfSize = m_GeoPar->getElectrodeHalfSize(layer, hasChimney) * CLHEP::cm;
804 G4Box* electrodeBox =
805 new G4Box(name,
806 electrodeHalfSize.x(), electrodeHalfSize.y(), electrodeHalfSize.z()
807 );
808 G4LogicalVolume* electrodeLogical =
809 new G4LogicalVolume(electrodeBox,
810 Materials::get("G4_GLASS_PLATE"),
811 logicalName(electrodeBox)
812 );
813 electrodeLogical->SetVisAttributes(m_VisAttributes.front()); // invisible
814 // Place two gas volumes inside electrodes
815 sprintf(name, "BKLM.Layer%02d%sGasSolid", layer, (hasChimney ? "Chimney" : ""));
816 const CLHEP::Hep3Vector gasHalfSize = m_GeoPar->getGasHalfSize(layer, hasChimney) * CLHEP::cm;
817 G4Box* gasBox =
818 new G4Box(name,
819 gasHalfSize.x(), gasHalfSize.y(), gasHalfSize.z()
820 );
821 G4LogicalVolume* gasLogical =
822 new G4LogicalVolume(gasBox,
823 Materials::get("RPCGas"),
824 logicalName(gasBox),
825 0, // use global field manager
826 m_Sensitive, // this is the only sensitive volume in BKLM
827 0 // no user limits
828 );
829 m_VisAttributes.push_back(new G4VisAttributes(true));
830 m_VisAttributes.back()->SetColour(1.0, 0.5, 0.0);
831 gasLogical->SetVisAttributes(m_VisAttributes.back());
832 new G4PVPlacement(G4TranslateX3D(-0.5 * electrodeHalfSize.x()),
833 gasLogical,
834 physicalName(gasLogical),
835 electrodeLogical,
836 false,
837 BKLM_INNER,
838 false
839 );
840
841 new G4PVPlacement(G4TranslateX3D(+0.5 * electrodeHalfSize.x()),
842 gasLogical,
843 physicalName(gasLogical),
844 electrodeLogical,
845 false,
846 BKLM_OUTER,
847 false
848 );
849 new G4PVPlacement(G4TranslateZ3D(0.0),
850 electrodeLogical,
851 physicalName(electrodeLogical),
852 interiorLogical,
853 false,
854 1,
855 false
856 );
857}
const CLHEP::Hep3Vector getGasHalfSize(int layer, bool hasChimney) const
Get the size (dx,dy,dz) of the detector module's gas gaps of specified layer.
Definition: GeometryPar.cc:555
const CLHEP::Hep3Vector getElectrodeHalfSize(int layer, bool hasChimney) const
Get the size (dx,dy,dz) of the detector module's electrode of specified layer.
Definition: GeometryPar.cc:548

◆ putScintsInInterior()

void putScintsInInterior ( G4LogicalVolume *  interiorLogical,
int  section,
int  sector,
int  layer,
bool  hasChimney 
)
private

Put the scintillators into each detector module's interior (module is itself in an air gap)

Definition at line 859 of file GeoBKLMCreator.cc.

860{
861 char name[80] = "";
862 sprintf(name, "BKLM.Layer%02d%sAirSolid", layer, (hasChimney ? "Chimney" : ""));
863 const CLHEP::Hep3Vector airHalfSize = m_GeoPar->getAirHalfSize(layer, hasChimney) * CLHEP::cm;
864 G4Box* airBox =
865 new G4Box(name,
866 airHalfSize.x(), airHalfSize.y(), airHalfSize.z()
867 );
868 G4LogicalVolume* airLogical =
869 new G4LogicalVolume(airBox,
870 Materials::get("G4_AIR"),
871 logicalName(airBox)
872 );
873 airLogical->SetVisAttributes(m_VisAttributes.front()); // invisible
874 sprintf(name, "BKLM.Layer%02d%sScintEnvelopeSolid", layer, (hasChimney ? "Chimney" : ""));
875 double mppcHousingHalfLength = m_GeoPar->getMPPCHousingHalfLength() * CLHEP::cm;
876 const CLHEP::Hep3Vector envelopeHalfSize = m_GeoPar->getScintEnvelopeHalfSize(layer, hasChimney) * CLHEP::cm +
877 CLHEP::Hep3Vector(0.0, mppcHousingHalfLength, mppcHousingHalfLength);
878 G4Box* scintEnvelopeBox =
879 new G4Box(name,
880 envelopeHalfSize.x(), envelopeHalfSize.y(), envelopeHalfSize.z()
881 );
882 G4LogicalVolume* innerEnvelopeLogical =
883 new G4LogicalVolume(scintEnvelopeBox,
884 Materials::get("G4_AIR"),
885 logicalName(scintEnvelopeBox)
886 );
887 innerEnvelopeLogical->SetVisAttributes(m_VisAttributes.front()); // invisible
888 double scintHalfHeight = m_GeoPar->getScintHalfHeight() * CLHEP::cm;
889 double scintHalfWidth = m_GeoPar->getScintHalfWidth() * CLHEP::cm;
890
891 int envelopeOffsetSign = m_GeoPar->getScintEnvelopeOffsetSign(layer);
892 const Module* module = m_GeoPar->findModule(section == BKLMElementNumbers::c_ForwardSection, sector, layer);
893 for (int scint = 1; scint <= m_GeoPar->getNPhiScints(layer); ++scint) {
894 double scintHalfLength = module->getPhiScintHalfLength(scint) * CLHEP::cm;
895 double scintPosition = module->getPhiScintPosition(scint) * CLHEP::cm;
896 G4LogicalVolume* scintLogical = getScintLogical(scintHalfHeight, scintHalfWidth, scintHalfLength,
897 mppcHousingHalfLength);
898 new G4PVPlacement(G4Translate3D(0.0, scintPosition + mppcHousingHalfLength * envelopeOffsetSign, 0.0),
899 scintLogical,
900 physicalName(scintLogical),
901 innerEnvelopeLogical,
902 false,
903 scint,
904 false
905 );
906 }
907 G4LogicalVolume* outerEnvelopeLogical =
908 new G4LogicalVolume(scintEnvelopeBox,
909 Materials::get("G4_AIR"),
910 logicalName(scintEnvelopeBox)
911 );
912 outerEnvelopeLogical->SetVisAttributes(m_VisAttributes.front()); // invisible
913 for (int scint = 1; scint <= m_GeoPar->getNZScints(hasChimney); ++scint) {
914 double scintHalfLength = module->getZScintHalfLength(scint) * CLHEP::cm;
915 double scintOffset = module->getZScintOffset(scint) * CLHEP::cm;
916 double scintPosition = module->getZScintPosition(scint) * CLHEP::cm;
917 G4LogicalVolume* scintLogical = getScintLogical(scintHalfHeight, scintHalfWidth, scintHalfLength,
918 mppcHousingHalfLength);
919 new G4PVPlacement(G4Translate3D(0.0, scintOffset, scintPosition - mppcHousingHalfLength) * G4RotateX3D(M_PI_2 * envelopeOffsetSign),
920 scintLogical,
921 physicalName(scintLogical),
922 outerEnvelopeLogical,
923 false,
924 scint,
925 false
926 );
927 }
928 CLHEP::Hep3Vector envelopeOffset = m_GeoPar->getScintEnvelopeOffset(layer, hasChimney) * CLHEP::cm +
929 CLHEP::Hep3Vector(0.0, -mppcHousingHalfLength, mppcHousingHalfLength);
930 new G4PVPlacement(G4Translate3D(-envelopeHalfSize.x(), envelopeOffset.y() * envelopeOffsetSign, envelopeOffset.z()),
931 innerEnvelopeLogical,
932 physicalName(innerEnvelopeLogical),
933 airLogical,
934 false,
935 BKLM_INNER,
936 false
937 );
938 new G4PVPlacement(G4Translate3D(+envelopeHalfSize.x(), envelopeOffset.y() * envelopeOffsetSign, envelopeOffset.z()),
939 outerEnvelopeLogical,
940 physicalName(outerEnvelopeLogical),
941 airLogical,
942 false,
943 BKLM_OUTER,
944 false
945 );
946
947 // Place readout carriers and preamplifiers along module perimeter
948 double containerHalfSizeZ = m_GeoPar->getReadoutContainerHalfSize().z() * CLHEP::cm;
949 G4LogicalVolume* readoutContainerLogical = getReadoutContainerLogical();
950 for (int station = 1; station <= m_GeoPar->getNReadoutStation(); ++station) {
951 double stationPosition = m_GeoPar->getReadoutStationPosition(station) * CLHEP::cm;
952 G4Transform3D xform;
953 if (m_GeoPar->getReadoutStationIsPhi(station)) {
954 xform = G4Translate3D(0.0, stationPosition, airHalfSize.z() - containerHalfSizeZ);
955 } else {
956 xform = G4Translate3D(0.0,
957 (containerHalfSizeZ - airHalfSize.y()) * envelopeOffsetSign,
958 airHalfSize.z() + stationPosition
959 ) * G4RotateX3D(M_PI_2 * envelopeOffsetSign);
960 // Don't place all z-readout stations in chimney module.
961 if (fabs(xform.getTranslation().z()) > airHalfSize.z())
962 continue;
963 }
964 sprintf(name, "BKLM.ReadoutContainer%dLayer%02d%sPhysical", station, layer, (hasChimney ? "Chimney" : ""));
965 new G4PVPlacement(xform,
966 readoutContainerLogical,
967 name,
968 airLogical,
969 false,
970 station,
971 false
972 );
973 }
974
975 // Place the air container with scints, MPPCs and preamps in the interior container
976 new G4PVPlacement(G4TranslateX3D(m_GeoPar->getPolystyreneOffsetX() * CLHEP::cm),
977 airLogical,
978 physicalName(airLogical),
979 interiorLogical,
980 false,
981 1,
982 false
983 );
984}
G4LogicalVolume * getReadoutContainerLogical(void)
Get pointer to readout-container logical volume.
G4LogicalVolume * getScintLogical(double, double, double, double)
Get pointer to scintillator logical volume.
double getScintHalfHeight(void) const
Get the height of the entire volume of a scintillator strip (including TiO2 coating)
Definition: GeometryPar.h:112
int getNPhiScints(int layer) const
Get the number of phi-measuring scintillators in a scintillator module.
Definition: GeometryPar.cc:579
double getScintHalfWidth(void) const
Get the height of the entire volume of a scintillator strip (including TiO2 coating)
Definition: GeometryPar.h:118
const CLHEP::Hep3Vector getScintEnvelopeOffset(int layer, bool hasChimney) const
Get the shift (dx,dy,dz) of the scintillator detector module's scintillator envelope within its enclo...
Definition: GeometryPar.cc:633
int getNReadoutStation(void) const
Get the number of preamplifier readout stations.
Definition: GeometryPar.h:493
const CLHEP::Hep3Vector getScintEnvelopeHalfSize(int layer, bool hasChimney) const
Get the size (dx,dy,dz) of the scintillator detector module's scintillator envelope.
Definition: GeometryPar.cc:571
bool getReadoutStationIsPhi(int station) const
Get the selector for phi (true) or z (false) readout station.
Definition: GeometryPar.h:499
int getNZScints(bool isChimney) const
Get the number of z-measuring scintillators in a scintillator module.
Definition: GeometryPar.h:274
double getPolystyreneOffsetX(void) const
Get the radial offset of the scintillator detector module's active envelope due to difference in poly...
Definition: GeometryPar.cc:586
double getReadoutStationPosition(int station) const
Get the position of each readout station.
Definition: GeometryPar.h:505
int getScintEnvelopeOffsetSign(int layer) const
Get the sign (+/-1) of scintillator-envelope's shift along y axis within its enclosing module for MPP...
Definition: GeometryPar.h:91
const CLHEP::Hep3Vector getAirHalfSize(int layer, bool hasChimney) const
Get the size (dx,dy,dz) of the scintillator detector module's air filler.
Definition: GeometryPar.cc:564

◆ putSectorsInEnd()

void putSectorsInEnd ( G4LogicalVolume *  endLogical,
int  section 
)
private

Put each sector into the forward or backward end.

Definition at line 178 of file GeoBKLMCreator.cc.

179{
180 if (m_SectorTube == nullptr) {
182 new G4Tubs("BKLM.SectorSolid",
183 m_GeoPar->getSolenoidOuterRadius() * CLHEP::cm,
184 m_GeoPar->getOuterRadius() * CLHEP::cm / cos(0.5 * m_SectorDphi),
186 -0.5 * m_SectorDphi,
188 );
189 }
190 char name[80] = "";
191 for (int s = 0; s < m_GeoPar->getNSector(); ++s) {
192 int sector = (section == BKLMElementNumbers::c_ForwardSection ? s : ((12 - s) % 8)) + 1;
193 bool hasChimney = (section == BKLMElementNumbers::c_BackwardSection) && (sector == BKLMElementNumbers::c_ChimneySector);
194 bool hasInnerSupport = (sector <= m_GeoPar->getNSector() / 2 + 1);
195 sprintf(name, "BKLM.%sSector%dLogical", (section == BKLMElementNumbers::c_ForwardSection ? "Forward" : "Backward"), sector);
196 m_SectorLogical[section][sector - 1] =
197 new G4LogicalVolume(m_SectorTube,
198 Materials::get("G4_AIR"),
199 name
200 );
201 m_SectorLogical[section][sector - 1]->SetVisAttributes(m_VisAttributes.front()); // invisible
202 putCapInSector(m_SectorLogical[section][sector - 1], hasChimney);
203 putInnerRegionInSector(m_SectorLogical[section][sector - 1], hasInnerSupport, hasChimney);
204 putLayersInSector(m_SectorLogical[section][sector - 1], section, sector, hasChimney);
205 new G4PVPlacement(G4RotateZ3D(m_SectorDphi * s),
206 m_SectorLogical[section][sector - 1],
207 physicalName(m_SectorLogical[section][sector - 1]),
208 endLogical,
209 false,
210 sector,
211 false
212 );
213 }
214}
@ c_ChimneySector
Chimney sector: BB3 in 1-based notation; BB2 in 0-based notation.
void putLayersInSector(G4LogicalVolume *, int, int, bool)
Put the layers into each sector.
void putCapInSector(G4LogicalVolume *, bool)
Put the cap (at maximum |z|) into each sector.
void putInnerRegionInSector(G4LogicalVolume *, bool, bool)
Put the inner-radius region into each sector.

◆ putVoidInInnerRegion()

void putVoidInInnerRegion ( G4LogicalVolume *  innerIronLogical,
bool  hasInnerSupport,
bool  hasChimney 
)
private

Put the air void into the inner-radius region.

Definition at line 325 of file GeoBKLMCreator.cc.

326{
327
328 // Carve out an air void from the inner-region iron, leaving only the ribs
329 // at the azimuthal edges
330 if (m_InnerAirSolid == nullptr) {
331 const double r = m_GeoPar->getLayerInnerRadius(1) * CLHEP::cm - m_RibShift;
332 const double z[2] = { -m_SectorDz, +m_SectorDz};
333 const double rInner[2] = {0.0, 0.0};
334 const double rOuter[2] = {r, r};
335 G4Polyhedra* innerAirPolygon =
336 new G4Polyhedra("BKLM.InnerAirPolygon",
337 -0.5 * m_SectorDphi,
339 1,
340 2, z, rInner, rOuter
341 );
343 new G4SubtractionSolid("BKLM.InnerAirSolid",
344 innerAirPolygon,
346 G4TranslateX3D(-m_RibShift)
347 );
348 }
349 int newLvol = (hasInnerSupport ? 2 : 0) + (hasChimney ? 1 : 0);
350 if (m_InnerAirLogical[newLvol] == nullptr) {
351 m_InnerAirLogical[newLvol] =
352 new G4LogicalVolume(m_InnerAirSolid,
353 Materials::get("G4_AIR"),
354 (hasChimney ? "BKLM.InnerAirChimneyLogical" : "BKLM.InnerAirLogical")
355 );
356 m_InnerAirLogical[newLvol]->SetVisAttributes(m_VisAttributes.front()); // invisible
357 if (hasInnerSupport) {
360 }
361 }
362 new G4PVPlacement(G4TranslateX3D(m_RibShift),
363 m_InnerAirLogical[newLvol],
365 innerIronLogical,
366 false,
367 1,
368 false
369 );
370}
void putLayer1SupportInInnerVoid(G4LogicalVolume *, bool)
Put the layer-0 support plate into the inner region's air void (sectors 1..5 only)
void putLayer1BracketsInInnerVoid(G4LogicalVolume *, bool)
Put the layer-0 support plate's brackets into the inner region's air void (sectors 1....

Member Data Documentation

◆ m_BracketLogical

G4LogicalVolume* m_BracketLogical
private

Pointer to logical volume for bracket.

Definition at line 193 of file GeoBKLMCreator.h.

◆ m_CapLogical

G4LogicalVolume* m_CapLogical[2]
private

Pointer to logical volumes for cap [hasChimney].

Definition at line 175 of file GeoBKLMCreator.h.

◆ m_CapSolid

G4Polyhedra* m_CapSolid
private

Pointer to solid for cap.

Definition at line 172 of file GeoBKLMCreator.h.

◆ m_GeoPar

GeometryPar* m_GeoPar
private

Pointer to the BKLM geometry accessor.

Definition at line 157 of file GeoBKLMCreator.h.

◆ m_InnerAirLogical

G4LogicalVolume* m_InnerAirLogical[4]
private

Pointer to logical volumes for inner air [hasInnerSupport | hasChimney].

Definition at line 187 of file GeoBKLMCreator.h.

◆ m_InnerAirSolid

G4VSolid* m_InnerAirSolid
private

Pointer to solid for inner air.

Definition at line 184 of file GeoBKLMCreator.h.

◆ m_InnerIronLogical

G4LogicalVolume* m_InnerIronLogical[4]
private

Pointer to logical volumes for inner iron [hasInnerSupport | hasChimney].

Definition at line 181 of file GeoBKLMCreator.h.

◆ m_InnerIronSolid

G4VSolid* m_InnerIronSolid
private

Pointer to solid for inner iron [hasInnerSupport | hasChimney].

Definition at line 178 of file GeoBKLMCreator.h.

◆ m_LayerGapLogical

G4LogicalVolume* m_LayerGapLogical[12 *BKLMElementNumbers::getMaximalLayerNumber()]
private

Pointers to logical volumes for air gap in each layer [side/bottom/top | isFlipped | hasChimney | layer-1].

Definition at line 205 of file GeoBKLMCreator.h.

◆ m_LayerGapSolid

G4Box* m_LayerGapSolid[2 *BKLMElementNumbers::getMaximalLayerNumber()]
private

Pointers to solids for air gap in each layer [hasChimney | layer-1].

Definition at line 202 of file GeoBKLMCreator.h.

◆ m_LayerIronLogical

G4LogicalVolume* m_LayerIronLogical[12 *BKLMElementNumbers::getMaximalLayerNumber()]
private

Pointers to logical volumes for iron in each layer [side/bottom/top | isFlipped | hasChimney | layer-1].

Definition at line 199 of file GeoBKLMCreator.h.

◆ m_LayerIronSolid

G4Polyhedra* m_LayerIronSolid[BKLMElementNumbers::getMaximalLayerNumber()]
private

Pointers to solids for iron in each layer [layer-1].

Definition at line 196 of file GeoBKLMCreator.h.

◆ m_LayerModuleLogical

G4LogicalVolume* m_LayerModuleLogical[2 *BKLMElementNumbers::getMaximalLayerNumber()]
private

Pointers to logical volumes for detector modules in each layer's air gap [hasChimney | layer-1].

Definition at line 208 of file GeoBKLMCreator.h.

◆ m_MPPCHousingLogical

G4LogicalVolume* m_MPPCHousingLogical
private

Pointer to logical volume for MPPC housing.

Definition at line 217 of file GeoBKLMCreator.h.

◆ m_Names

std::vector<G4String*> m_Names
private

Vector of pointers to G4String objects (volume names)

Definition at line 232 of file GeoBKLMCreator.h.

◆ m_ReadoutContainerLogical

G4LogicalVolume* m_ReadoutContainerLogical
private

Pointer to logical volume for scint preamplifier/carrier container.

Definition at line 220 of file GeoBKLMCreator.h.

◆ m_RibShift

double m_RibShift
private

Radial displacement of polygon to create an azimuthal iron rib.

Definition at line 169 of file GeoBKLMCreator.h.

◆ m_ScintLogicals

std::vector<G4LogicalVolume*> m_ScintLogicals
private

Pointers to logical volumes for scintillator strips.

Definition at line 226 of file GeoBKLMCreator.h.

◆ m_SectorDphi

double m_SectorDphi
private

Angular extent of one sector.

Definition at line 163 of file GeoBKLMCreator.h.

◆ m_SectorDz

double m_SectorDz
private

Half-length of one sector.

Definition at line 166 of file GeoBKLMCreator.h.

◆ m_SectorLogical

G4LogicalVolume* m_SectorLogical[2][BKLMElementNumbers::getMaximalSectorNumber()]
private

Pointers to logical volumes for each sector [fb-1][sector-1].

Definition at line 214 of file GeoBKLMCreator.h.

◆ m_SectorTube

G4Tubs* m_SectorTube
private

Pointer to solid for sector's enclosing tube.

Definition at line 211 of file GeoBKLMCreator.h.

◆ m_Sensitive

G4VSensitiveDetector* m_Sensitive
private

Pointer to the BKLM SensitiveDetector processor.

Definition at line 160 of file GeoBKLMCreator.h.

◆ m_SolenoidTube

G4Tubs* m_SolenoidTube
private

Pointer to solid for solenoid.

Definition at line 223 of file GeoBKLMCreator.h.

◆ m_SupportLogical

G4LogicalVolume* m_SupportLogical[2]
private

Pointer to logical volumes for support structure [hasChimney].

Definition at line 190 of file GeoBKLMCreator.h.

◆ m_VisAttributes

std::vector<G4VisAttributes*> m_VisAttributes
private

Vector of pointers to G4VisAttributes objects.

Definition at line 229 of file GeoBKLMCreator.h.


The documentation for this class was generated from the following files: