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