File indexing completed on 2025-02-23 09:21:03
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 #include "DetectorConstruction.hh"
0034
0035 #include "DetectorMessenger.hh"
0036
0037 #include "G4Box.hh"
0038 #include "G4FieldManager.hh"
0039 #include "G4GeometryManager.hh"
0040 #include "G4LogicalVolume.hh"
0041 #include "G4LogicalVolumeStore.hh"
0042 #include "G4Material.hh"
0043 #include "G4NistManager.hh"
0044 #include "G4PVPlacement.hh"
0045 #include "G4PhysicalConstants.hh"
0046 #include "G4PhysicalVolumeStore.hh"
0047 #include "G4RunManager.hh"
0048 #include "G4SolidStore.hh"
0049 #include "G4SystemOfUnits.hh"
0050 #include "G4TransportationManager.hh"
0051 #include "G4UniformMagField.hh"
0052 #include "G4UnitsTable.hh"
0053
0054
0055
0056 DetectorConstruction::DetectorConstruction()
0057 : G4VUserDetectorConstruction(), fMagField(nullptr), fLAbsor(nullptr), fLWorld(nullptr)
0058 {
0059
0060 fAbsorSizeX = fAbsorSizeYZ = 20 * cm;
0061 fWorldSizeX = fWorldSizeYZ = 1.2 * fAbsorSizeX;
0062
0063 fTallyNumber = 0;
0064 for (G4int j = 0; j < kMaxTally; j++) {
0065 fTallySize[j] = fTallyPosition[j] = G4ThreeVector(0., 0., 0.);
0066 fTallyMass[j] = 0.;
0067 fLTally[j] = nullptr;
0068 }
0069
0070 DefineMaterials();
0071
0072
0073 fDetectorMessenger = new DetectorMessenger(this);
0074 }
0075
0076
0077
0078 DetectorConstruction::~DetectorConstruction()
0079 {
0080 delete fDetectorMessenger;
0081 }
0082
0083
0084
0085 void DetectorConstruction::DefineMaterials()
0086 {
0087
0088
0089
0090 G4double z, a;
0091
0092 G4Element* H = new G4Element("Hydrogen", "H", z = 1, a = 1.008 * g / mole);
0093 G4Element* N = new G4Element("Nitrogen", "N", z = 7, a = 14.01 * g / mole);
0094 G4Element* O = new G4Element("Oxygen", "O", z = 8, a = 16.00 * g / mole);
0095
0096
0097
0098
0099 G4double density, temperature, pressure;
0100 G4int ncomponents, natoms;
0101 G4double fractionmass;
0102
0103 G4Material* H2O = new G4Material("Water", density = 1.0 * g / cm3, ncomponents = 2);
0104 H2O->AddElement(H, natoms = 2);
0105 H2O->AddElement(O, natoms = 1);
0106 H2O->GetIonisation()->SetMeanExcitationEnergy(78.0 * eV);
0107
0108
0109 G4NistManager::Instance()->BuildMaterialWithNewDensity("Water_1.05", "G4_WATER", 1.05 * g / cm3);
0110
0111 G4Material* Air = new G4Material("Air", density = 1.290 * mg / cm3, ncomponents = 2);
0112 Air->AddElement(N, fractionmass = 0.7);
0113 Air->AddElement(O, fractionmass = 0.3);
0114
0115 density = 1.e-5 * g / cm3;
0116 pressure = 2.e-2 * bar;
0117 temperature = STP_Temperature;
0118 G4Material* vac = new G4Material("TechVacuum", density, 1, kStateGas, temperature, pressure);
0119 vac->AddMaterial(Air, 1.);
0120
0121 density = universe_mean_density;
0122 pressure = 3.e-18 * pascal;
0123 temperature = 2.73 * kelvin;
0124 G4Material* vacuum = new G4Material("Galactic", z = 1, a = 1.008 * g / mole, density, kStateGas,
0125 temperature, pressure);
0126
0127
0128 fAbsorMaterial = H2O;
0129 fWorldMaterial = vacuum;
0130 }
0131
0132
0133
0134 G4VPhysicalVolume* DetectorConstruction::Construct()
0135 {
0136
0137
0138 G4Box* sWorld = new G4Box("World",
0139 fWorldSizeX / 2, fWorldSizeYZ / 2, fWorldSizeYZ / 2);
0140
0141 fLWorld = new G4LogicalVolume(sWorld,
0142 fWorldMaterial,
0143 "World");
0144
0145 G4VPhysicalVolume* pWorld = new G4PVPlacement(0,
0146 G4ThreeVector(0., 0., 0.),
0147 fLWorld,
0148 "World",
0149 0,
0150 false,
0151 0);
0152
0153
0154
0155 G4Box* sAbsor = new G4Box("Absorber",
0156 fAbsorSizeX / 2, fAbsorSizeYZ / 2, fAbsorSizeYZ / 2);
0157
0158 fLAbsor = new G4LogicalVolume(sAbsor,
0159 fAbsorMaterial,
0160 "Absorber");
0161
0162 new G4PVPlacement(0,
0163 G4ThreeVector(0., 0., 0.),
0164 fLAbsor,
0165 "Absorber",
0166 fLWorld,
0167 false,
0168 0);
0169
0170
0171
0172 if (fTallyNumber > 0) {
0173 for (G4int j = 0; j < fTallyNumber; ++j) {
0174 G4Box* sTally =
0175 new G4Box("Tally", fTallySize[j].x() / 2, fTallySize[j].y() / 2, fTallySize[j].z() / 2);
0176
0177 fLTally[j] = new G4LogicalVolume(sTally, fAbsorMaterial, "Tally");
0178
0179 new G4PVPlacement(0,
0180 fTallyPosition[j],
0181 fLTally[j],
0182 "Tally",
0183 fLAbsor,
0184 false,
0185 j + 1);
0186
0187 fTallyMass[j] =
0188 fTallySize[j].x() * fTallySize[j].y() * fTallySize[j].z() * (fAbsorMaterial->GetDensity());
0189 }
0190 }
0191
0192 PrintParameters();
0193
0194
0195
0196
0197 return pWorld;
0198 }
0199
0200
0201
0202 void DetectorConstruction::PrintParameters() const
0203 {
0204 G4cout << *(G4Material::GetMaterialTable()) << G4endl;
0205 G4cout << "\n---------------------------------------------------------\n";
0206 G4cout << "---> The Absorber is " << G4BestUnit(fAbsorSizeX, "Length") << " of "
0207 << fAbsorMaterial->GetName() << G4endl;
0208 G4cout << "\n---------------------------------------------------------\n";
0209
0210 if (fTallyNumber > 0) {
0211 G4cout << "---> There are " << fTallyNumber << " tallies : " << G4endl;
0212 for (G4int j = 0; j < fTallyNumber; ++j) {
0213 G4cout << "fTally " << j << ": " << fAbsorMaterial->GetName()
0214 << ", mass = " << G4BestUnit(fTallyMass[j], "Mass")
0215 << " size = " << G4BestUnit(fTallySize[j], "Length")
0216 << " position = " << G4BestUnit(fTallyPosition[j], "Length") << G4endl;
0217 }
0218 G4cout << "\n---------------------------------------------------------\n";
0219 }
0220 }
0221
0222
0223
0224 void DetectorConstruction::SetSizeX(G4double value)
0225 {
0226 fAbsorSizeX = value;
0227 fWorldSizeX = 1.2 * fAbsorSizeX;
0228 }
0229
0230
0231
0232 void DetectorConstruction::SetSizeYZ(G4double value)
0233 {
0234 fAbsorSizeYZ = value;
0235 fWorldSizeYZ = 1.2 * fAbsorSizeYZ;
0236 }
0237
0238
0239
0240 void DetectorConstruction::SetMaterial(const G4String& materialChoice)
0241 {
0242
0243 G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(materialChoice);
0244 if (pttoMaterial && pttoMaterial != fAbsorMaterial) {
0245
0246 fAbsorMaterial = pttoMaterial;
0247 for (G4int j = 0; j < fTallyNumber; ++j) {
0248 if (fLTally[j]) {
0249 fLTally[j]->SetMaterial(pttoMaterial);
0250 fTallyMass[j] =
0251 fTallySize[j].x() * fTallySize[j].y() * fTallySize[j].z() * (pttoMaterial->GetDensity());
0252 }
0253 }
0254 if (fLAbsor) {
0255 fLAbsor->SetMaterial(fAbsorMaterial);
0256 G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0257 }
0258 }
0259 }
0260
0261
0262
0263 void DetectorConstruction::SetWorldMaterial(const G4String& materialChoice)
0264 {
0265
0266 G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(materialChoice);
0267 if (pttoMaterial && pttoMaterial != fWorldMaterial) {
0268 fWorldMaterial = pttoMaterial;
0269 if (fLWorld) {
0270 fLWorld->SetMaterial(fAbsorMaterial);
0271 G4RunManager::GetRunManager()->PhysicsHasBeenModified();
0272 }
0273 }
0274 }
0275
0276
0277
0278 void DetectorConstruction::SetMagField(G4double fieldValue)
0279 {
0280
0281 G4FieldManager* fieldMgr = G4TransportationManager::GetTransportationManager()->GetFieldManager();
0282
0283 if (fMagField) delete fMagField;
0284
0285 if (fieldValue != 0.)
0286 {
0287 fMagField = new G4UniformMagField(G4ThreeVector(0., 0., fieldValue));
0288 fieldMgr->SetDetectorField(fMagField);
0289 fieldMgr->CreateChordFinder(fMagField);
0290 }
0291 else {
0292 fMagField = nullptr;
0293 fieldMgr->SetDetectorField(fMagField);
0294 }
0295 }
0296
0297
0298 void DetectorConstruction::SetTallyNumber(G4int value)
0299 {
0300 if (value >= 0 && value < kMaxTally) {
0301 fTallyNumber = value;
0302 }
0303 else {
0304 G4cout << "### DetectorConstruction::SetTallyNumber WARNING: wrong tally "
0305 << "number " << value << " is ignored" << G4endl;
0306 }
0307 }
0308
0309
0310
0311 void DetectorConstruction::SetTallySize(G4int j, const G4ThreeVector& value)
0312 {
0313 if (j >= 0 && j < kMaxTally) {
0314 fTallySize[j] = value;
0315 }
0316 else {
0317 G4cout << "### DetectorConstruction::SetTallyNumber WARNING: wrong tally "
0318 << "number " << j << " is ignored" << G4endl;
0319 }
0320 }
0321
0322
0323
0324 void DetectorConstruction::SetTallyPosition(G4int j, const G4ThreeVector& value)
0325 {
0326 if (j >= 0 && j < kMaxTally) {
0327 fTallyPosition[j] = value;
0328 }
0329 else {
0330 G4cout << "### DetectorConstruction::SetTallyPosition WARNING: wrong tally "
0331 << "number " << j << " is ignored" << G4endl;
0332 }
0333 }
0334
0335 G4double DetectorConstruction::GetTallyMass(G4int j) const
0336 {
0337 if (j >= 0 && j < kMaxTally) {
0338 return fTallyMass[j];
0339 }
0340 else {
0341 G4cout << "### DetectorConstruction::GetTallyMass WARNING: wrong tally "
0342 << "number " << j << " is ignored" << G4endl;
0343 return 0.0;
0344 }
0345 }
0346
0347 const G4LogicalVolume* DetectorConstruction::GetLogicalTally(G4int j) const
0348 {
0349 if (j >= 0 && j < kMaxTally) {
0350 return fLTally[j];
0351 }
0352 else {
0353 G4cout << "### DetectorConstruction::GetLOgicalTally WARNING: wrong tally "
0354 << "number " << j << " is ignored" << G4endl;
0355 return nullptr;
0356 }
0357 }
0358
0359