File indexing completed on 2026-04-01 07:51:16
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 "OpNoviceDetectorConstruction.hh"
0030
0031 #include "OpNoviceDetectorMessenger.hh"
0032
0033 #include "G4Box.hh"
0034 #include "G4Element.hh"
0035 #include "G4GDMLParser.hh"
0036 #include "G4LogicalBorderSurface.hh"
0037 #include "G4LogicalSkinSurface.hh"
0038 #include "G4LogicalVolume.hh"
0039 #include "G4Material.hh"
0040 #include "G4OpticalSurface.hh"
0041 #include "G4PVPlacement.hh"
0042 #include "G4SystemOfUnits.hh"
0043 #include "G4ThreeVector.hh"
0044
0045
0046 OpNoviceDetectorConstruction::OpNoviceDetectorConstruction() : G4VUserDetectorConstruction()
0047 {
0048
0049 fDetectorMessenger = new OpNoviceDetectorMessenger(this);
0050 }
0051
0052
0053 OpNoviceDetectorConstruction::~OpNoviceDetectorConstruction()
0054 {
0055 delete fDetectorMessenger;
0056 }
0057
0058
0059 G4VPhysicalVolume* OpNoviceDetectorConstruction::Construct()
0060 {
0061 G4bool checkOverlaps = true;
0062
0063 G4double a, z, density;
0064 G4int nelements;
0065
0066
0067 auto N = new G4Element("Nitrogen", "N", z = 7, a = 14.01 * g / mole);
0068 auto O = new G4Element("Oxygen", "O", z = 8, a = 16.00 * g / mole);
0069 auto air = new G4Material("Air", density = 1.29 * mg / cm3, nelements = 2);
0070 air->AddElement(N, 70. * perCent);
0071 air->AddElement(O, 30. * perCent);
0072
0073
0074 auto H = new G4Element("Hydrogen", "H", z = 1, a = 1.01 * g / mole);
0075 auto water = new G4Material("Water", density = 1.0 * g / cm3, nelements = 2);
0076 water->AddElement(H, 2);
0077 water->AddElement(O, 1);
0078
0079
0080
0081 std::vector<G4double> photonEnergy = {
0082 2.034 * eV, 2.068 * eV, 2.103 * eV, 2.139 * eV, 2.177 * eV, 2.216 * eV, 2.256 * eV, 2.298 * eV,
0083 2.341 * eV, 2.386 * eV, 2.433 * eV, 2.481 * eV, 2.532 * eV, 2.585 * eV, 2.640 * eV, 2.697 * eV,
0084 2.757 * eV, 2.820 * eV, 2.885 * eV, 2.954 * eV, 3.026 * eV, 3.102 * eV, 3.181 * eV, 3.265 * eV,
0085 3.353 * eV, 3.446 * eV, 3.545 * eV, 3.649 * eV, 3.760 * eV, 3.877 * eV, 4.002 * eV, 4.136 * eV};
0086
0087
0088 std::vector<G4double> refractiveIndex1 = {
0089 1.3435, 1.344, 1.3445, 1.345, 1.3455, 1.346, 1.3465, 1.347, 1.3475, 1.348, 1.3485,
0090 1.3492, 1.35, 1.3505, 1.351, 1.3518, 1.3522, 1.3530, 1.3535, 1.354, 1.3545, 1.355,
0091 1.3555, 1.356, 1.3568, 1.3572, 1.358, 1.3585, 1.359, 1.3595, 1.36, 1.3608};
0092 std::vector<G4double> absorption = {
0093 3.448 * m, 4.082 * m, 6.329 * m, 9.174 * m, 12.346 * m, 13.889 * m, 15.152 * m, 17.241 * m,
0094 18.868 * m, 20.000 * m, 26.316 * m, 35.714 * m, 45.455 * m, 47.619 * m, 52.632 * m, 52.632 * m,
0095 55.556 * m, 52.632 * m, 52.632 * m, 47.619 * m, 45.455 * m, 41.667 * m, 37.037 * m, 33.333 * m,
0096 30.000 * m, 28.500 * m, 27.000 * m, 24.500 * m, 22.000 * m, 19.500 * m, 17.500 * m, 14.500 * m};
0097
0098
0099
0100 G4double scintilFastArray[]{1.0, 1.0};
0101 G4double energyArray[]{2.034 * eV, 4.136 * eV};
0102 G4int lenArray = 2;
0103
0104 std::vector<G4double> scintilSlow = {
0105 0.01, 1.00, 2.00, 3.00, 4.00, 5.00, 6.00, 7.00, 8.00, 9.00, 8.00, 7.00, 6.00, 4.00, 3.00, 2.00,
0106 1.00, 0.01, 1.00, 2.00, 3.00, 4.00, 5.00, 6.00, 7.00, 8.00, 9.00, 8.00, 7.00, 6.00, 5.00, 4.00};
0107
0108 auto myMPT1 = new G4MaterialPropertiesTable();
0109
0110
0111
0112
0113
0114
0115 G4int numEntries = 1;
0116 myMPT1->AddProperty("RINDEX", &photonEnergy[0], &refractiveIndex1[0], numEntries);
0117
0118 for (size_t i = 1; i < photonEnergy.size(); ++i) {
0119 myMPT1->AddEntry("RINDEX", photonEnergy[i], refractiveIndex1[i]);
0120 }
0121
0122
0123 if (myMPT1->GetProperty("RINDEX")->GetVectorLength()
0124 != myMPT1->GetProperty("GROUPVEL")->GetVectorLength())
0125 {
0126 G4ExceptionDescription ed;
0127 ed << "Error calculating group velocities. Incorrect number of entries "
0128 "in group velocity material property vector.";
0129 G4Exception("OpNovice::OpNoviceDetectorConstruction", "OpNovice001", FatalException, ed);
0130 }
0131
0132
0133
0134 myMPT1->AddProperty("ABSLENGTH", photonEnergy, absorption, false, true);
0135
0136
0137
0138
0139 myMPT1->AddProperty("SCINTILLATIONCOMPONENT1", energyArray, scintilFastArray, lenArray);
0140
0141 myMPT1->AddProperty("SCINTILLATIONCOMPONENT2", photonEnergy, scintilSlow, false, true);
0142 myMPT1->AddConstProperty("SCINTILLATIONYIELD", 50. / MeV);
0143 myMPT1->AddConstProperty("RESOLUTIONSCALE", 1.0);
0144 myMPT1->AddConstProperty("SCINTILLATIONTIMECONSTANT1", 1. * ns);
0145 myMPT1->AddConstProperty("SCINTILLATIONTIMECONSTANT2", 10. * ns);
0146 myMPT1->AddConstProperty("SCINTILLATIONYIELD1", 0.8);
0147 myMPT1->AddConstProperty("SCINTILLATIONYIELD2", 0.2);
0148 std::vector<G4double> energy_water = {
0149 1.56962 * eV, 1.58974 * eV, 1.61039 * eV, 1.63157 * eV, 1.65333 * eV, 1.67567 * eV,
0150 1.69863 * eV, 1.72222 * eV, 1.74647 * eV, 1.77142 * eV, 1.7971 * eV, 1.82352 * eV,
0151 1.85074 * eV, 1.87878 * eV, 1.90769 * eV, 1.93749 * eV, 1.96825 * eV, 1.99999 * eV,
0152 2.03278 * eV, 2.06666 * eV, 2.10169 * eV, 2.13793 * eV, 2.17543 * eV, 2.21428 * eV,
0153 2.25454 * eV, 2.29629 * eV, 2.33962 * eV, 2.38461 * eV, 2.43137 * eV, 2.47999 * eV,
0154 2.53061 * eV, 2.58333 * eV, 2.63829 * eV, 2.69565 * eV, 2.75555 * eV, 2.81817 * eV,
0155 2.88371 * eV, 2.95237 * eV, 3.02438 * eV, 3.09999 * eV, 3.17948 * eV, 3.26315 * eV,
0156 3.35134 * eV, 3.44444 * eV, 3.54285 * eV, 3.64705 * eV, 3.75757 * eV, 3.87499 * eV,
0157 3.99999 * eV, 4.13332 * eV, 4.27585 * eV, 4.42856 * eV, 4.59258 * eV, 4.76922 * eV,
0158 4.95999 * eV, 5.16665 * eV, 5.39129 * eV, 5.63635 * eV, 5.90475 * eV, 6.19998 * eV};
0159
0160
0161
0162
0163 std::vector<G4double> mie_water = {
0164 167024.4 * m, 158726.7 * m, 150742 * m, 143062.5 * m, 135680.2 * m, 128587.4 * m,
0165 121776.3 * m, 115239.5 * m, 108969.5 * m, 102958.8 * m, 97200.35 * m, 91686.86 * m,
0166 86411.33 * m, 81366.79 * m, 76546.42 * m, 71943.46 * m, 67551.29 * m, 63363.36 * m,
0167 59373.25 * m, 55574.61 * m, 51961.24 * m, 48527.00 * m, 45265.87 * m, 42171.94 * m,
0168 39239.39 * m, 36462.50 * m, 33835.68 * m, 31353.41 * m, 29010.30 * m, 26801.03 * m,
0169 24720.42 * m, 22763.36 * m, 20924.88 * m, 19200.07 * m, 17584.16 * m, 16072.45 * m,
0170 14660.38 * m, 13343.46 * m, 12117.33 * m, 10977.70 * m, 9920.416 * m, 8941.407 * m,
0171 8036.711 * m, 7202.470 * m, 6434.927 * m, 5730.429 * m, 5085.425 * m, 4496.467 * m,
0172 3960.210 * m, 3473.413 * m, 3032.937 * m, 2635.746 * m, 2278.907 * m, 1959.588 * m,
0173 1675.064 * m, 1422.710 * m, 1200.004 * m, 1004.528 * m, 833.9666 * m, 686.1063 * m};
0174
0175
0176 G4double mie_water_const[3] = {0.99, 0.99, 0.8};
0177
0178 myMPT1->AddProperty("MIEHG", energy_water, mie_water, false, true);
0179 myMPT1->AddConstProperty("MIEHG_FORWARD", mie_water_const[0]);
0180 myMPT1->AddConstProperty("MIEHG_BACKWARD", mie_water_const[1]);
0181 myMPT1->AddConstProperty("MIEHG_FORWARD_RATIO", mie_water_const[2]);
0182
0183 G4cout << "Water G4MaterialPropertiesTable:" << G4endl;
0184 myMPT1->DumpTable();
0185
0186 water->SetMaterialPropertiesTable(myMPT1);
0187
0188
0189 water->GetIonisation()->SetBirksConstant(0.126 * mm / MeV);
0190
0191
0192 std::vector<G4double> refractiveIndex2 = {1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
0193 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
0194 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0};
0195
0196 auto myMPT2 = new G4MaterialPropertiesTable();
0197 myMPT2->AddProperty("RINDEX", photonEnergy, refractiveIndex2);
0198
0199 G4cout << "Air G4MaterialPropertiesTable:" << G4endl;
0200 myMPT2->DumpTable();
0201
0202 air->SetMaterialPropertiesTable(myMPT2);
0203
0204
0205
0206
0207 auto world_box = new G4Box("World", fWorld_x, fWorld_y, fWorld_z);
0208 auto world_log = new G4LogicalVolume(world_box, air, "World");
0209 G4VPhysicalVolume* world_phys = new G4PVPlacement(nullptr, G4ThreeVector(), world_log, "world",
0210 nullptr, false, 0, checkOverlaps);
0211
0212
0213 auto expHall_box = new G4Box("expHall", fExpHall_x, fExpHall_y, fExpHall_z);
0214 auto expHall_log = new G4LogicalVolume(expHall_box, air, "expHall");
0215 G4VPhysicalVolume* expHall_phys =
0216 new G4PVPlacement(nullptr, G4ThreeVector(), expHall_log, "expHall", world_log, false, 0);
0217
0218
0219 auto waterTank_box = new G4Box("Tank", fTank_x, fTank_y, fTank_z);
0220 auto waterTank_log = new G4LogicalVolume(waterTank_box, water, "Tank");
0221 G4VPhysicalVolume* waterTank_phys =
0222 new G4PVPlacement(nullptr, G4ThreeVector(), waterTank_log, "Tank", expHall_log, false, 0);
0223
0224
0225 auto bubbleAir_box = new G4Box("Bubble", fBubble_x, fBubble_y, fBubble_z);
0226 auto bubbleAir_log = new G4LogicalVolume(bubbleAir_box, air, "Bubble");
0227 new G4PVPlacement(nullptr, G4ThreeVector(0, 2.5 * m, 0), bubbleAir_log, "Bubble", waterTank_log,
0228 false, 0);
0229
0230
0231
0232
0233 auto opWaterSurface = new G4OpticalSurface("WaterSurface");
0234 opWaterSurface->SetType(dielectric_LUTDAVIS);
0235 opWaterSurface->SetFinish(Rough_LUT);
0236 opWaterSurface->SetModel(DAVIS);
0237
0238 auto waterSurface =
0239 new G4LogicalBorderSurface("WaterSurface", waterTank_phys, expHall_phys, opWaterSurface);
0240
0241 auto opticalSurface = dynamic_cast<G4OpticalSurface*>(
0242 waterSurface->GetSurface(waterTank_phys, expHall_phys)->GetSurfaceProperty());
0243 if (opticalSurface) opticalSurface->DumpInfo();
0244
0245
0246 auto opAirSurface = new G4OpticalSurface("AirSurface");
0247 opAirSurface->SetType(dielectric_dielectric);
0248 opAirSurface->SetFinish(polished);
0249 opAirSurface->SetModel(glisur);
0250
0251 auto airSurface = new G4LogicalSkinSurface("AirSurface", bubbleAir_log, opAirSurface);
0252
0253 opticalSurface =
0254 dynamic_cast<G4OpticalSurface*>(airSurface->GetSurface(bubbleAir_log)->GetSurfaceProperty());
0255 if (opticalSurface) opticalSurface->DumpInfo();
0256
0257
0258
0259 std::vector<G4double> ephoton = {2.034 * eV, 4.136 * eV};
0260
0261
0262 std::vector<G4double> reflectivity = {0.3, 0.5};
0263 std::vector<G4double> efficiency = {0.8, 1.0};
0264
0265 auto myST2 = new G4MaterialPropertiesTable();
0266
0267 myST2->AddProperty("REFLECTIVITY", ephoton, reflectivity);
0268 myST2->AddProperty("EFFICIENCY", ephoton, efficiency);
0269 if (fVerbose) {
0270 G4cout << "Air Surface G4MaterialPropertiesTable:" << G4endl;
0271 myST2->DumpTable();
0272 }
0273 opAirSurface->SetMaterialPropertiesTable(myST2);
0274
0275 if (fDumpGdml) {
0276 auto parser = new G4GDMLParser();
0277 parser->Write(fDumpGdmlFileName, world_phys);
0278 }
0279
0280
0281
0282 G4String ed;
0283 if (myMPT1->GetProperty("USERDEFINED") != nullptr) {
0284 ed = "USERDEFINED != nullptr";
0285 PrintError(ed);
0286 }
0287 myMPT1->AddProperty("USERDEFINED", energy_water, mie_water, true, true);
0288 if (myMPT1->GetProperty("USERDEFINED") == nullptr) {
0289 ed = "USERDEFINED == nullptr";
0290 PrintError(ed);
0291 }
0292 [[maybe_unused]] G4int index_userdefined = -1;
0293 if (myMPT1->GetProperty("USERDEFINED") != nullptr) {
0294 index_userdefined = myMPT1->GetPropertyIndex("USERDEFINED");
0295 }
0296 if (!(index_userdefined >= 0
0297 && index_userdefined < (G4int)myMPT1->GetMaterialPropertyNames().size()))
0298 {
0299 ed = "USERDEFINED index out of range";
0300 PrintError(ed);
0301 }
0302 myMPT1->RemoveProperty("USERDEFINED");
0303 if (myMPT1->GetProperty("USERDEFINED") != nullptr) {
0304 ed = "USERDEFINED != nullptr at end";
0305 PrintError(ed);
0306 }
0307
0308 if (myMPT1->ConstPropertyExists("USERDEFINEDCONST") == true) {
0309 ed = "ConstProperty USERDEFINEDCONST already exists.";
0310 PrintError(ed);
0311 }
0312 myMPT1->AddConstProperty("USERDEFINEDCONST", 3.14, true);
0313 if (myMPT1->ConstPropertyExists("USERDEFINEDCONST") == false) {
0314 ed = "ConstProperty USERDEFINEDCONST doesn't exist.";
0315 PrintError(ed);
0316 }
0317 [[maybe_unused]] G4int index_pi = -1;
0318 if (myMPT1->ConstPropertyExists("USERDEFINEDCONST") == true) {
0319 index_pi = myMPT1->GetConstPropertyIndex("USERDEFINEDCONST");
0320 }
0321 if (!(index_pi >= 0 && index_pi < (G4int)myMPT1->GetMaterialConstPropertyNames().size())) {
0322 ed = "ConstProperty USERDEFINEDCONST index out of range.";
0323 PrintError(ed);
0324 }
0325 myMPT1->RemoveConstProperty("USERDEFINEDCONST");
0326 if (myMPT1->ConstPropertyExists("USERDEFINEDCONST") == true) {
0327 ed = "ConstProperty USERDEFINEDCONST still exists.";
0328 PrintError(ed);
0329 }
0330
0331
0332
0333 return world_phys;
0334 }
0335
0336
0337 void OpNoviceDetectorConstruction::SetDumpGdml(G4bool val)
0338 {
0339 fDumpGdml = val;
0340 }
0341
0342
0343 G4bool OpNoviceDetectorConstruction::IsDumpGdml() const
0344 {
0345 return fDumpGdml;
0346 }
0347
0348
0349 void OpNoviceDetectorConstruction::SetVerbose(G4bool val)
0350 {
0351 fVerbose = val;
0352 }
0353
0354
0355 G4bool OpNoviceDetectorConstruction::IsVerbose() const
0356 {
0357 return fVerbose;
0358 }
0359
0360
0361 void OpNoviceDetectorConstruction::SetDumpGdmlFile(G4String filename)
0362 {
0363 fDumpGdmlFileName = filename;
0364 }
0365
0366
0367 G4String OpNoviceDetectorConstruction::GetDumpGdmlFile() const
0368 {
0369 return fDumpGdmlFileName;
0370 }
0371
0372
0373 void OpNoviceDetectorConstruction::PrintError(G4String ed)
0374 {
0375 G4Exception("OpNoviceDetectorConstruction:MaterialProperty test", "op001", FatalException, ed);
0376 }