File indexing completed on 2026-06-25 07:54:44
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
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 #include "TSDetectorConstruction.hh"
0054
0055 #include "G4Box.hh"
0056 #include "G4Colour.hh"
0057 #include "G4LogicalVolume.hh"
0058 #include "G4Material.hh"
0059 #include "G4MultiFunctionalDetector.hh"
0060 #include "G4NistManager.hh"
0061 #include "G4PSEnergyDeposit.hh"
0062 #include "G4PSNofStep.hh"
0063 #include "G4PVPlacement.hh"
0064 #include "G4RunManager.hh"
0065 #include "G4SDManager.hh"
0066 #include "G4UnitsTable.hh"
0067 #include "G4UserLimits.hh"
0068 #include "G4VPhysicalVolume.hh"
0069 #include "G4VisAttributes.hh"
0070
0071 using namespace CLHEP;
0072
0073
0074
0075 TSDetectorConstruction* TSDetectorConstruction::fgInstance = 0;
0076
0077
0078
0079 TSDetectorConstruction* TSDetectorConstruction::Instance()
0080 {
0081 return fgInstance;
0082 }
0083
0084
0085
0086 TSDetectorConstruction::TSDetectorConstruction()
0087 : fWorldPhys(0),
0088 fWorldMaterialName("G4_Galactic"),
0089 fTargetMaterialName("G4_B"),
0090 fCasingMaterialName("G4_WATER"),
0091 fWorldDim(G4ThreeVector(0.5 * m, 0.5 * m, 0.5 * m)),
0092 fTargetDim(G4ThreeVector(0.5 * m, 0.5 * m, 0.5 * m)),
0093 fTargetSections(G4ThreeVector(5, 5, 5)),
0094 fMfdName("Target_MFD")
0095 {
0096 fgInstance = this;
0097 }
0098
0099
0100
0101 TSDetectorConstruction::~TSDetectorConstruction()
0102 {
0103 fgInstance = 0;
0104 }
0105
0106
0107
0108 G4VPhysicalVolume* TSDetectorConstruction::Construct()
0109 {
0110 return ConstructWorld(ConstructMaterials());
0111 }
0112
0113
0114
0115 TSDetectorConstruction::MaterialCollection_t TSDetectorConstruction::ConstructMaterials()
0116 {
0117 MaterialCollection_t materials;
0118 G4NistManager* nist = G4NistManager::Instance();
0119
0120 materials["World"] = nist->FindOrBuildMaterial(fWorldMaterialName);
0121 materials["Target"] = nist->FindOrBuildMaterial(fTargetMaterialName);
0122 materials["Casing"] = nist->FindOrBuildMaterial(fCasingMaterialName);
0123
0124 return materials;
0125 }
0126
0127
0128
0129 G4VPhysicalVolume* TSDetectorConstruction::ConstructWorld(const MaterialCollection_t& materials)
0130 {
0131 G4UserLimits* steplimit = new G4UserLimits(0.1 * (fTargetDim.z() / fTargetSections.z()));
0132 G4bool check_overlap = false;
0133
0134 G4Box* world_solid =
0135 new G4Box("World", 0.5 * fWorldDim.x(), 0.5 * fWorldDim.y(), 0.5 * fWorldDim.z());
0136 G4LogicalVolume* world_log =
0137 new G4LogicalVolume(world_solid, materials.find("World")->second, "World");
0138 fWorldPhys =
0139 new G4PVPlacement(0, G4ThreeVector(0.), "World", world_log, 0, false, 0, check_overlap);
0140
0141 G4int nz = fTargetSections.z();
0142 G4int ny = fTargetSections.y();
0143 G4int nx = fTargetSections.x();
0144
0145
0146 G4double sx = fTargetDim.x() / fTargetSections.x();
0147 G4double sy = fTargetDim.y() / fTargetSections.y();
0148 G4double sz = fTargetDim.z() / fTargetSections.z();
0149
0150
0151
0152
0153
0154
0155
0156 G4VisAttributes* red = new G4VisAttributes(G4Color(1., 0., 0., 1.0));
0157 G4VisAttributes* green = new G4VisAttributes(G4Color(0., 1., 0., 0.25));
0158 G4VisAttributes* blue = new G4VisAttributes(G4Color(0., 0., 1., 0.1));
0159 G4VisAttributes* white = new G4VisAttributes(G4Color(1., 1., 1., 1.));
0160
0161 white->SetVisibility(true);
0162 red->SetVisibility(true);
0163 green->SetVisibility(true);
0164 blue->SetVisibility(true);
0165
0166 white->SetForceWireframe(true);
0167 red->SetForceSolid(true);
0168 green->SetForceSolid(true);
0169 blue->SetForceSolid(true);
0170
0171 world_log->SetVisAttributes(white);
0172
0173 for (G4int k = 0; k < nz; ++k)
0174 for (G4int j = 0; j < ny; ++j)
0175 for (G4int i = 0; i < nx; ++i) {
0176
0177 G4double dx = 0.5 * sx + static_cast<G4double>(i) * sx - 0.5 * fWorldDim.x();
0178 G4double dy = 0.5 * sy + static_cast<G4double>(j) * sy - 0.5 * fWorldDim.y();
0179 G4double dz = 0.5 * sz + static_cast<G4double>(k) * sz - 0.5 * fWorldDim.z();
0180 G4ThreeVector td = G4ThreeVector(dx, dy, -dz);
0181
0182 std::stringstream ss_name;
0183 ss_name << "Target_" << i << "_" << j << "_" << k;
0184
0185 G4Box* target_solid = new G4Box(ss_name.str(), 0.5 * sx, 0.5 * sy, 0.5 * sz);
0186
0187 G4Material* target_material = 0;
0188 G4bool is_casing = true;
0189
0190 if (j == 0 || j + 1 == ny || i == 0 || i + 1 == nx || (nz > 1 && (k == 0 || k + 1 == nz)))
0191 target_material = materials.find("Casing")->second;
0192 else {
0193 target_material = materials.find("Target")->second;
0194 is_casing = false;
0195 }
0196
0197 G4LogicalVolume* target_log =
0198 new G4LogicalVolume(target_solid, target_material, ss_name.str());
0199
0200 target_log->SetUserLimits(steplimit);
0201
0202 new G4PVPlacement(0, td, ss_name.str(), target_log, fWorldPhys, true,
0203 k * nx * ny + j * nx + i, check_overlap);
0204
0205 fScoringVolumes.insert(target_log);
0206
0207 if (is_casing)
0208 target_log->SetVisAttributes(blue);
0209 else {
0210
0211 G4bool even_z = (k % 2 == 0) ? true : false;
0212 G4bool even_y = (j % 2 == 0) ? true : false;
0213 G4bool even_x = (i % 2 == 0) ? true : false;
0214
0215 G4VisAttributes* theColor = nullptr;
0216
0217 if ((even_z)) {
0218 if ((even_y && even_x) || (!even_y && !even_x))
0219 theColor = red;
0220 else
0221 theColor = green;
0222 }
0223 else
0224 {
0225 if ((!even_y && even_x) || (even_y && !even_x))
0226 theColor = red;
0227 else
0228 theColor = green;
0229 }
0230
0231 target_log->SetVisAttributes(theColor);
0232 }
0233 }
0234
0235 return fWorldPhys;
0236 }
0237
0238
0239
0240 void TSDetectorConstruction::ConstructSDandField()
0241 {
0242
0243
0244
0245
0246 G4MultiFunctionalDetector* MFDet = new G4MultiFunctionalDetector(fMfdName);
0247 G4SDManager::GetSDMpointer()->AddNewDetector(MFDet);
0248 G4VPrimitiveScorer* edep = new G4PSEnergyDeposit("EnergyDeposit");
0249 MFDet->RegisterPrimitive(edep);
0250 G4VPrimitiveScorer* nstep = new G4PSNofStep("NumberOfSteps");
0251 MFDet->RegisterPrimitive(nstep);
0252
0253
0254 for (auto ite : fScoringVolumes) {
0255 SetSensitiveDetector(ite, MFDet);
0256 }
0257 }
0258
0259