File indexing completed on 2026-04-08 07:52:48
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 #include "DetectorConstruction.hh"
0030
0031 #include "G4Box.hh"
0032 #include "G4LogicalVolume.hh"
0033 #include "G4MultiFunctionalDetector.hh"
0034 #include "G4NistManager.hh"
0035 #include "G4PSDoseDeposit.hh"
0036 #include "G4PSEnergyDeposit.hh"
0037 #include "G4PVPlacement.hh"
0038 #include "G4PhysicalConstants.hh"
0039 #include "G4RotationMatrix.hh"
0040 #include "G4SDManager.hh"
0041 #include "G4SystemOfUnits.hh"
0042 #include "G4Transform3D.hh"
0043 #include "G4Tubs.hh"
0044 #include "G4VisAttributes.hh"
0045
0046 namespace B3
0047 {
0048
0049
0050
0051 DetectorConstruction::DetectorConstruction()
0052 {
0053 DefineMaterials();
0054 }
0055
0056
0057
0058 void DetectorConstruction::DefineMaterials()
0059 {
0060 G4NistManager* man = G4NistManager::Instance();
0061
0062 G4bool isotopes = false;
0063
0064 G4Element* O = man->FindOrBuildElement("O", isotopes);
0065 G4Element* Si = man->FindOrBuildElement("Si", isotopes);
0066 G4Element* Lu = man->FindOrBuildElement("Lu", isotopes);
0067
0068 auto LSO = new G4Material("Lu2SiO5", 7.4 * g / cm3, 3);
0069 LSO->AddElement(Lu, 2);
0070 LSO->AddElement(Si, 1);
0071 LSO->AddElement(O, 5);
0072 }
0073
0074
0075
0076 G4VPhysicalVolume* DetectorConstruction::Construct()
0077 {
0078
0079
0080 G4double cryst_dX = 6 * cm, cryst_dY = 6 * cm, cryst_dZ = 3 * cm;
0081 G4int nb_cryst = 32;
0082 G4int nb_rings = 9;
0083
0084 G4double dPhi = twopi / nb_cryst, half_dPhi = 0.5 * dPhi;
0085 G4double cosdPhi = std::cos(half_dPhi);
0086 G4double tandPhi = std::tan(half_dPhi);
0087
0088 G4double ring_R1 = 0.5 * cryst_dY / tandPhi;
0089 G4double ring_R2 = (ring_R1 + cryst_dZ) / cosdPhi;
0090
0091 G4double detector_dZ = nb_rings * cryst_dX;
0092
0093 G4NistManager* nist = G4NistManager::Instance();
0094 G4Material* default_mat = nist->FindOrBuildMaterial("G4_AIR");
0095 G4Material* cryst_mat = nist->FindOrBuildMaterial("Lu2SiO5");
0096
0097
0098
0099
0100 G4double world_sizeXY = 2.4 * ring_R2;
0101 G4double world_sizeZ = 1.2 * detector_dZ;
0102
0103 auto solidWorld =
0104 new G4Box("World",
0105 0.5 * world_sizeXY, 0.5 * world_sizeXY, 0.5 * world_sizeZ);
0106
0107 auto logicWorld = new G4LogicalVolume(solidWorld,
0108 default_mat,
0109 "World");
0110
0111 auto physWorld = new G4PVPlacement(nullptr,
0112 G4ThreeVector(),
0113 logicWorld,
0114 "World",
0115 nullptr,
0116 false,
0117 0,
0118 fCheckOverlaps);
0119
0120
0121
0122
0123 auto solidRing = new G4Tubs("Ring", ring_R1, ring_R2, 0.5 * cryst_dX, 0., twopi);
0124
0125 auto logicRing = new G4LogicalVolume(solidRing,
0126 default_mat,
0127 "Ring");
0128
0129
0130
0131
0132 G4double gap = 0.5 * mm;
0133 G4double dX = cryst_dX - gap, dY = cryst_dY - gap;
0134 auto solidCryst = new G4Box("crystal", dX / 2, dY / 2, cryst_dZ / 2);
0135
0136 auto logicCryst = new G4LogicalVolume(solidCryst,
0137 cryst_mat,
0138 "CrystalLV");
0139
0140
0141
0142 for (G4int icrys = 0; icrys < nb_cryst; icrys++) {
0143 G4double phi = icrys * dPhi;
0144 G4RotationMatrix rotm = G4RotationMatrix();
0145 rotm.rotateY(90 * deg);
0146 rotm.rotateZ(phi);
0147 G4ThreeVector uz = G4ThreeVector(std::cos(phi), std::sin(phi), 0.);
0148 G4ThreeVector position = (ring_R1 + 0.5 * cryst_dZ) * uz;
0149 G4Transform3D transform = G4Transform3D(rotm, position);
0150
0151 new G4PVPlacement(transform,
0152 logicCryst,
0153 "crystal",
0154 logicRing,
0155 false,
0156 icrys,
0157 fCheckOverlaps);
0158 }
0159
0160
0161
0162
0163 auto solidDetector = new G4Tubs("Detector", ring_R1, ring_R2, 0.5 * detector_dZ, 0., twopi);
0164
0165 auto logicDetector = new G4LogicalVolume(solidDetector,
0166 default_mat,
0167 "Detector");
0168
0169
0170
0171
0172 G4double OG = -0.5 * (detector_dZ + cryst_dX);
0173 for (G4int iring = 0; iring < nb_rings; iring++) {
0174 OG += cryst_dX;
0175 new G4PVPlacement(nullptr,
0176 G4ThreeVector(0, 0, OG),
0177 logicRing,
0178 "ring",
0179 logicDetector,
0180 false,
0181 iring,
0182 fCheckOverlaps);
0183 }
0184
0185
0186
0187
0188 new G4PVPlacement(nullptr,
0189 G4ThreeVector(),
0190 logicDetector,
0191 "Detector",
0192 logicWorld,
0193 false,
0194 0,
0195 fCheckOverlaps);
0196
0197
0198
0199
0200 G4double patient_radius = 8 * cm;
0201 G4double patient_dZ = 10 * cm;
0202 G4Material* patient_mat = nist->FindOrBuildMaterial("G4_BRAIN_ICRP");
0203
0204 auto solidPatient = new G4Tubs("Patient", 0., patient_radius, 0.5 * patient_dZ, 0., twopi);
0205
0206 auto logicPatient = new G4LogicalVolume(solidPatient,
0207 patient_mat,
0208 "PatientLV");
0209
0210
0211
0212
0213 new G4PVPlacement(nullptr,
0214 G4ThreeVector(),
0215 logicPatient,
0216 "Patient",
0217 logicWorld,
0218 false,
0219 0,
0220 fCheckOverlaps);
0221
0222
0223
0224 logicRing->SetVisAttributes(G4VisAttributes::GetInvisible());
0225 logicDetector->SetVisAttributes(G4VisAttributes::GetInvisible());
0226
0227
0228 G4cout << *(G4Material::GetMaterialTable()) << G4endl;
0229
0230
0231
0232 return physWorld;
0233 }
0234
0235
0236
0237 void DetectorConstruction::ConstructSDandField()
0238 {
0239 G4SDManager::GetSDMpointer()->SetVerboseLevel(1);
0240
0241
0242
0243 auto cryst = new G4MultiFunctionalDetector("crystal");
0244 G4SDManager::GetSDMpointer()->AddNewDetector(cryst);
0245 G4VPrimitiveScorer* primitiv1 = new G4PSEnergyDeposit("edep");
0246 cryst->RegisterPrimitive(primitiv1);
0247 SetSensitiveDetector("CrystalLV", cryst);
0248
0249
0250
0251 auto patient = new G4MultiFunctionalDetector("patient");
0252 G4SDManager::GetSDMpointer()->AddNewDetector(patient);
0253 G4VPrimitiveScorer* primitiv2 = new G4PSDoseDeposit("dose");
0254 patient->RegisterPrimitive(primitiv2);
0255 SetSensitiveDetector("PatientLV", patient);
0256 }
0257
0258
0259
0260 }