File indexing completed on 2026-09-11 08:31:06
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 #include "Par04ParallelFullWorld.hh"
0031
0032 #include "Par04ParallelFullSensitiveDetector.hh"
0033 #include "Par04ParallelMessenger.hh"
0034
0035
0036 #include "G4AutoDelete.hh"
0037 #include "G4Colour.hh"
0038 #include "G4LogicalVolume.hh"
0039 #include "G4Material.hh"
0040 #include "G4NistManager.hh"
0041 #include "G4PVPlacement.hh"
0042 #include "G4PVReplica.hh"
0043 #include "G4SDManager.hh"
0044 #include "G4SystemOfUnits.hh"
0045 #include "G4ThreeVector.hh"
0046 #include "G4Tubs.hh"
0047 #include "G4UnitsTable.hh"
0048 #include "G4VPhysicalVolume.hh"
0049 #include "G4VisAttributes.hh"
0050 #include "globals.hh"
0051
0052
0053
0054 Par04ParallelFullWorld::Par04ParallelFullWorld(G4String aWorldName,
0055 const Par04DetectorConstruction* aMassDetector)
0056 : G4VUserParallelWorld(aWorldName), fMassDetector(aMassDetector)
0057 {
0058 fParallelMessenger = new Par04ParallelMessenger(this);
0059 fNbOfLayers = fMassDetector->GetNbOfLayers();
0060 }
0061
0062
0063
0064 Par04ParallelFullWorld::~Par04ParallelFullWorld() = default;
0065
0066
0067
0068 void Par04ParallelFullWorld::Construct()
0069 {
0070
0071 G4Material* dummy = nullptr;
0072
0073
0074 auto parallelLogicalVolume = GetWorld()->GetLogicalVolume();
0075
0076 G4double detectorInnerRadius = fMassDetector->GetInnerRadius();
0077 G4double detectorLength = fMassDetector->GetLength();
0078 G4double fullLayerThickness =
0079 fMassDetector->GetAbsorberThickness(0) + fMassDetector->GetAbsorberThickness(1);
0080 G4double sensitiveLayerOffset = 0;
0081 if (fMassDetector->GetAbsorberSensitivity(0))
0082 fLayerThickness = fMassDetector->GetAbsorberThickness(0);
0083 else
0084 sensitiveLayerOffset = fMassDetector->GetAbsorberThickness(0);
0085 if (fMassDetector->GetAbsorberSensitivity(1))
0086 fLayerThickness += fMassDetector->GetAbsorberThickness(1);
0087
0088 fNbOfLayers = fMassDetector->GetNbOfLayers();
0089 G4double detectorRadius = fNbOfLayers * fullLayerThickness;
0090 G4double detectorOuterRadius = detectorInnerRadius + detectorRadius;
0091 G4double rowThickness = detectorLength / fNbOfRows;
0092 G4double full2Pi = 2. * CLHEP::pi * rad;
0093 Print();
0094
0095
0096
0097 auto solidDetector = new G4Tubs("Detector",
0098 detectorInnerRadius,
0099 detectorOuterRadius,
0100 detectorLength / 2.,
0101 0,
0102 full2Pi);
0103 auto logicDetector = new G4LogicalVolume(solidDetector,
0104 dummy,
0105 "Detector");
0106 new G4PVPlacement(0,
0107 G4ThreeVector(0, 0, 0),
0108 logicDetector,
0109 "Detector",
0110 parallelLogicalVolume,
0111 false,
0112 9999,
0113 true);
0114
0115
0116 auto solidRow =
0117 new G4Tubs("Row", detectorInnerRadius, detectorOuterRadius, rowThickness / 2., 0, full2Pi);
0118
0119 auto logicRow = new G4LogicalVolume(solidRow, dummy, "Row");
0120 if (fNbOfRows > 1)
0121 new G4PVReplica("Row", logicRow, logicDetector, kZAxis, fNbOfRows, rowThickness);
0122 else
0123 new G4PVPlacement(0, G4ThreeVector(), logicRow, "Row", logicDetector, false, 0);
0124
0125
0126 G4double cellPhi = full2Pi / fNbOfSlices;
0127 auto solidSlice =
0128 new G4Tubs("Slice", detectorInnerRadius, detectorOuterRadius, rowThickness / 2, 0, cellPhi);
0129 auto logicSlice = new G4LogicalVolume(solidSlice, dummy, "Slice");
0130 if (fNbOfLayers > 1 && fullLayerThickness == fLayerThickness) {
0131 new G4PVReplica("Slice", logicSlice, logicRow, kPhi, fNbOfSlices, cellPhi, -cellPhi);
0132 }
0133 else {
0134
0135 for (int iSlice = 0; iSlice < fNbOfSlices; iSlice++) {
0136 auto rotation = new G4RotationMatrix();
0137 rotation->setPhi((iSlice + 0.5) * cellPhi);
0138 new G4PVPlacement(rotation, G4ThreeVector(), logicSlice, "Slice_" + std::to_string(iSlice),
0139 logicRow, false, iSlice);
0140 }
0141 }
0142
0143
0144 G4VisAttributes attribs;
0145 attribs.SetColour(G4Colour(0, 1, 0, 0.1));
0146 attribs.SetForceSolid(true);
0147 if (fNbOfLayers > 1 && fullLayerThickness == fLayerThickness) {
0148 auto solidCell = new G4Tubs("Cell", detectorInnerRadius + sensitiveLayerOffset,
0149 detectorInnerRadius + sensitiveLayerOffset + fLayerThickness,
0150 rowThickness / 2, 0, cellPhi);
0151 fLogicalCell.push_back(new G4LogicalVolume(solidCell, dummy, "Cell_0"));
0152 new G4PVReplica("Cell", fLogicalCell.back(), logicSlice, kRho, fNbOfLayers, fLayerThickness,
0153 detectorInnerRadius);
0154 }
0155 else {
0156
0157 for (int iLayer = 0; iLayer < fNbOfLayers; iLayer++) {
0158 auto solidCell = new G4Tubs(
0159 "Cell_" + std::to_string(iLayer),
0160 detectorInnerRadius + iLayer * fullLayerThickness + sensitiveLayerOffset,
0161 detectorInnerRadius + iLayer * fullLayerThickness + sensitiveLayerOffset + fLayerThickness,
0162 rowThickness / 2, 0, cellPhi);
0163 fLogicalCell.push_back(
0164 new G4LogicalVolume(solidCell, dummy, "Cell_" + std::to_string(iLayer)));
0165 fLogicalCell.back()->SetVisAttributes(attribs);
0166 new G4PVPlacement(0, G4ThreeVector(), fLogicalCell.back(), "Cell_" + std::to_string(iLayer),
0167 logicSlice, false, iLayer);
0168 }
0169 }
0170 Print();
0171 }
0172
0173
0174
0175 void Par04ParallelFullWorld::ConstructSD()
0176 {
0177
0178 G4SDManager* SDman = G4SDManager::GetSDMpointer();
0179 Par04ParallelFullSensitiveDetector* caloSD =
0180 new Par04ParallelFullSensitiveDetector("parallelFullSD", fNbOfLayers, fNbOfSlices, fNbOfRows);
0181 SDman->AddNewDetector(caloSD);
0182 for (const auto& logicalCell : fLogicalCell)
0183 logicalCell->SetSensitiveDetector(caloSD);
0184 }
0185
0186
0187
0188 void Par04ParallelFullWorld::Print()
0189 {
0190 G4cout << "\n------------------------------------------------------"
0191 << "\n Readout geometry with physics layout is set in parallel geometry:\t"
0192 << "\n Cylindrical detector is divided along radius (layers), phi (slices), and z (rows)."
0193 << "\n Number of layers is determined by number of layers set in detector construction. "
0194 << "\n- Number of layers: " << fNbOfLayers << "\n------- Number of slices: " << fNbOfSlices
0195 << "\n- Number of rows: " << fNbOfRows;
0196 G4cout << "\n Readout will collect energy for full simulation.\n------- Therefore thickness is "
0197 << "only a thickness of sensitive absorbers = " << G4BestUnit(fLayerThickness, "Length")
0198 << "\n-----------------------------------------------------" << G4endl;
0199 }