From 6b1f7d425395f98c2498fa79bc1616f103575365 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Wed, 2 Apr 2025 00:42:41 +0100 Subject: [PATCH 01/52] updated for encapsulation --- src/geo/src/pmt/PMTConstruction.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/geo/src/pmt/PMTConstruction.cc b/src/geo/src/pmt/PMTConstruction.cc index 09da28cb..d886ad81 100644 --- a/src/geo/src/pmt/PMTConstruction.cc +++ b/src/geo/src/pmt/PMTConstruction.cc @@ -29,6 +29,8 @@ PMTConstruction *PMTConstruction::NewConstruction(DBLinkPtr table, G4LogicalVolu return new CubicPMTConstruction(table, mother); } else if (construction == "lappd") { return new LAPPDConstruction(table, mother); + } else if (construction == "encapsulated") { + return new EncapsulatedPMTConstruction(table, mother); } else { Log::Die("PMT construction \'" + construction + "\' does not exist."); } From 245c290d92763351797457c53da55a943e5d27df Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Wed, 2 Apr 2025 00:44:59 +0100 Subject: [PATCH 02/52] updated for encapsulation --- .../src/pmt/EncapsulatedPMTConstruction.cc | 955 ++++++++++++++++++ 1 file changed, 955 insertions(+) create mode 100644 src/geo/src/pmt/EncapsulatedPMTConstruction.cc diff --git a/src/geo/src/pmt/EncapsulatedPMTConstruction.cc b/src/geo/src/pmt/EncapsulatedPMTConstruction.cc new file mode 100644 index 00000000..fcf8b192 --- /dev/null +++ b/src/geo/src/pmt/EncapsulatedPMTConstruction.cc @@ -0,0 +1,955 @@ +// Adam T: A encapsulated pmt based off the Toroidal pmt construction model for +// button (some of the offesets will need adjusted for different pmt this will +// work for the r7081pe model) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace RAT { + +EncapsulatedPMTConstruction::EncapsulatedPMTConstruction( + DBLinkPtr table, G4LogicalVolume *mother) + : PMTConstruction("Encapsulated") { + body_phys = 0; + inner1_phys = 0; + inner2_phys = 0; + central_gap_phys = 0; + dynode_phys = 0; + encapsulation_phys = 0; + in_encapsulation_phys = 0; + front_encapsulation_phys = 0; + rear_encapsulation_phys = 0; + front_metal_encapsulaion_flange_phys = 0; + rear_metal_encapsulation_flange_phys = 0; + acrylic_flange_encapsulaion_phys = 0; + silica_bag_encapsulation_phys = 0; + cable_encapsulation_phys = 0; + optical_gel_encapsulation_phys = 0; + + log_pmt = 0; + + // Setup PMT parameters + fParams.faceGap = 0.1 * CLHEP::mm; + fParams.zEdge = table->GetDArray("z_edge"); + fParams.rhoEdge = table->GetDArray("rho_edge"); + fParams.zOrigin = table->GetDArray("z_origin"); + fParams.dynodeRadius = table->GetD("dynode_radius"); + fParams.dynodeTop = table->GetD("dynode_top"); + fParams.wallThickness = table->GetD("wall_thickness"); + // MFB + fParams.photocathode_MINrho = 0.0; + try { + fParams.photocathode_MINrho = table->GetD("photocathode_MINrho"); + } catch (DBNotFoundError &e) { + }; + fParams.photocathode_MAXrho = 0.0; + try { + fParams.photocathode_MAXrho = table->GetD("photocathode_MAXrho"); + } catch (DBNotFoundError &e) { + }; + + // Materials + fParams.exterior = mother->GetMaterial(); + fParams.glass = G4Material::GetMaterial(table->GetS("glass_material")); + fParams.dynode = G4Material::GetMaterial(table->GetS("dynode_material")); + fParams.vacuum = G4Material::GetMaterial(table->GetS("pmt_vacuum_material")); + std::string pc_surface_name = table->GetS("photocathode_surface"); + fParams.photocathode = Materials::optical_surface[pc_surface_name]; + std::string mirror_surface_name = table->GetS("mirror_surface"); + fParams.mirror = Materials::optical_surface[mirror_surface_name]; + fParams.dynode_surface = + Materials::optical_surface[table->GetS("dynode_surface")]; + + // Encapsulation + fParams.in_encapsulation_material = + G4Material::GetMaterial(table->GetS("inside_encapsulation_material")); + fParams.front_encapsulation_material = + G4Material::GetMaterial(table->GetS("front_encapsulation_material")); + fParams.rear_encapsulation_material = + G4Material::GetMaterial(table->GetS("rear_encapsulation_material")); + fParams.metal_flange_material = + G4Material::GetMaterial(table->GetS("metal_flange_material")); + fParams.acrylic_flange_material = + G4Material::GetMaterial(table->GetS("acrylic_flange_material")); + fParams.silica_bag_material = + G4Material::GetMaterial(table->GetS("silica_bag_material")); + fParams.cable_material = + G4Material::GetMaterial(table->GetS("cable_material")); + fParams.optical_gel_material = + G4Material::GetMaterial(table->GetS("optical_gel_material")); + + fParams.in_encapsulation_surface = + Materials::optical_surface[table->GetS("inside_encapsulation_material")]; + fParams.front_encapsulation_surface = + Materials::optical_surface[table->GetS("front_encapsulation_material")]; + fParams.rear_encapsulation_surface = + Materials::optical_surface[table->GetS("rear_encapsulation_material")]; + fParams.metal_flange_surface = + Materials::optical_surface[table->GetS("metal_flange_material")]; + fParams.acrylic_flange_surface = + Materials::optical_surface[table->GetS("acrylic_flange_material")]; + fParams.silica_bag_surface = + Materials::optical_surface[table->GetS("silica_bag_material")]; + fParams.cable_surface = + Materials::optical_surface[table->GetS("cable_material")]; + fParams.optical_gel_surface = + Materials::optical_surface[table->GetS("optical_gel_material")]; + + + + /* + + fParams.front_encapsulation_material = + G4Material::GetMaterial(table->GetS("front_encapsulation_material")); + fParams.rear_encapsulation_material = + G4Material::GetMaterial(table->GetS("rear_encapsulation_material")); + fParams.metal_flange_material = + G4Material::GetMaterial(table->GetS("metal_flange_material")); + fParams.acrylic_flange_material = + G4Material::GetMaterial(table->GetS("acrylic_flange_material")); + fParams.silica_bag_material = + G4Material::GetMaterial(table->GetS("silica_bag_material")); + fParams.cable_material = + G4Material::GetMaterial(table->GetS("cable_material")); + + fParams.front_encapsulation_surface = + Materials::optical_surface[table->GetS("front_encapsultion_material")]; + fParams.rear_encapsulation_surface = + Materials::optical_surface[table->GetS("rear_encapsulation_material")]; + fParams.metal_flange_surface = + Materials::optical_surface[table->GetS("metal_flange_material")]; + fParams.acrylic_flange_surface = + Materials::optical_surface[table->GetS("acrylic_flange_material")]; + fParams.silica_bag_surface = + Materials::optical_surface[table->GetS("silica_bag_material")]; + fParams.cable_surface = + Materials::optical_surface[table->GetS("cable_material")]; + */ + + if (fParams.photocathode == 0) { + Log::Die("EncapsulatedPMTConstruction error: Photocathode surface \"" + + pc_surface_name + "\" not found"); + } + + // Set new overall correction if requested (not included in individual) + try { + double efficiency_correction = table->GetD("efficiency_correction"); + fParams.efficiencyCorrection = efficiency_correction; + } catch (DBNotFoundError &e) { + } + + // --------------- Start building PMT geometry ------------------ + + // Setup for waveguide + fWaveguideFactory = 0; + try { + std::string waveguide = table->GetS("waveguide"); + std::string waveguide_desc = table->GetS("waveguide_desc"); + std::string waveguide_table, waveguide_index; + if (!DB::ParseTableName(waveguide_desc, waveguide_table, waveguide_index)) { + Log::Die("EncapsulatedPMTConstruction: Waveguide descriptor name is not " + "a valid RATDB table: " + + waveguide_desc); + } + + fWaveguideFactory = GlobalFactory::New(waveguide); + fWaveguideFactory->SetTable(waveguide_table, waveguide_index); + fParams.faceGap = fWaveguideFactory->GetZTop(); + fParams.minEnvelopeRadius = fWaveguideFactory->GetRadius(); + } catch (DBNotFoundError &e) { + } + + // Build PMT + fParams.useEnvelope = true; // disable the use of envelope volume for now + + assert(fParams.zEdge.size() == fParams.rhoEdge.size()); + assert(fParams.zEdge.size() == fParams.zOrigin.size() + 1); + assert(fParams.exterior); + assert(fParams.glass); + assert(fParams.vacuum); + assert(fParams.dynode); + assert(fParams.photocathode); + assert(fParams.mirror); +} + +G4LogicalVolume * +EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { + if (log_pmt) { + return log_pmt; + } + + // envelope cylinder + G4VSolid *envelope_solid = 0; + if (fParams.useEnvelope) { + envelope_solid = NewEnvelopeSolid(prefix + "_envelope_solid"); + } + + // glass body + GLG4TorusStack *body_solid = + (GLG4TorusStack *)BuildSolid(prefix + "_body_solid"); + + // inner vacuum + GLG4TorusStack *inner1_solid = new GLG4TorusStack(prefix + "_inner1_solid"); + GLG4TorusStack *inner2_solid = new GLG4TorusStack(prefix + "_inner2_solid"); + std::vector innerZEdge, innerRhoEdge; + G4double zLowestDynode; + int equatorIndex; + CalcInnerParams(body_solid, innerZEdge, innerRhoEdge, equatorIndex, + zLowestDynode); + inner1_solid->SetAllParameters(equatorIndex, &innerZEdge[0], &innerRhoEdge[0], + &fParams.zOrigin[0]); + inner2_solid->SetAllParameters( + fParams.zOrigin.size() - equatorIndex, &innerZEdge[equatorIndex], + &innerRhoEdge[equatorIndex], &fParams.zOrigin[equatorIndex]); + + // dynode volume + G4double hhDynode = (fParams.dynodeTop - zLowestDynode) / 2.0; + G4Tubs *dynode_solid = + new G4Tubs(prefix + "_dynode_solid", 0.0, + fParams.dynodeRadius, // solid cylinder (FIXME?) + hhDynode, // half height of cylinder + 0., CLHEP::twopi); // cylinder complete in phi + + // tolerance gap between inner1 and inner2, needed to prevent overlap due to + // floating point roundoff + G4double hhgap = + 0.5e-3; // half the needed gap between the front and back of the PMT + G4double toleranceGapRadius = + innerRhoEdge[equatorIndex]; // the outer radius of the gap needs to be + // equal to the inner radius of the PMT where + // inner1 and inner2 join + + G4Tubs *central_gap_solid = + new G4Tubs(prefix + "_central_gap_solid", 0.0, + toleranceGapRadius, // solid cylinder with same radius as PMT + hhgap, // half height of cylinder + 0., CLHEP::twopi); // cylinder complete in phi + + // ------------ Logical Volumes ------------- + G4LogicalVolume *envelope_log = 0, *body_log, *inner1_log, *inner2_log, + *dynode_log, *central_gap_log; + + if (fParams.useEnvelope) { + envelope_log = new G4LogicalVolume(envelope_solid, fParams.exterior, + prefix + "_envelope_log"); + } + + body_log = + new G4LogicalVolume(body_solid, fParams.glass, prefix + "_body_log"); + + inner1_log = + new G4LogicalVolume(inner1_solid, fParams.vacuum, prefix + "_inner1_log"); + + inner2_log = + new G4LogicalVolume(inner2_solid, fParams.vacuum, prefix + "_inner2_log"); + + dynode_log = + new G4LogicalVolume(dynode_solid, fParams.dynode, prefix + "_dynode_log"); + + central_gap_log = new G4LogicalVolume(central_gap_solid, fParams.vacuum, + prefix + "_central_gap_log"); + + ///// Encapsulaiton + // The default inner encapsulation diameter is: 40cm + // front and back perpendicular to the PMT direction + // rotation required to point in direction of pmtdir + // double angle_y = (-1.0)*atan2(pmtdir.x(), pmtdir.z()); + // double angle_x = atan2(pmtdir.y(), + // sqrt(pmtdir.x()*pmtdir.x()+pmtdir.z()*pmtdir.z())); + + // G4RotationMatrix* pmtrot = new G4RotationMatrix(); + // pmtrot->rotateY(angle_y); + // pmtrot->rotateX(angle_x);.. + + // fParams.front_encapsulation_material = + // G4Material::GetMaterial("nakano_acrylic"); + // fParams.front_encapsulation_surface = + // Materials::optical_surface[table->GetS("nakano_acrylic")]; + G4cout << "PMT encapsulation is added!! \n "; + double enc_radius = 20.0; // default radius + double enc_thickness = 0.8; // 8mm encapsulation thickness + +/* G4VSolid *inner_encapsulation_solid = 0; + inner_encapsulation_solid = optical_gel(prefix + "_inner_encapsulation_solid", body_solid); + inner_encapsulation_log = new G4LogicalVolume(inner_encapsulation_solid, // G4VSolid + fParams.front_encapsulation_material, // G4Material + prefix+"inner_encapsulation_log"); + + G4VSolid *inner_encapsulation_solid = + new G4Sphere("inner_encapsulation_solid", + (0.0)*CLHEP::cm, // rmin 20 cm + (enc_radius-0.001) * CLHEP::cm, // rmax: 20.8 cm + CLHEP::pi, CLHEP::twopi, // phi + 0., CLHEP::pi); // theta + //G4VSolid *inner_encapsulation_solid = new G4SubtractionSolid("inner_encapsulation_solid", inner_encapsulation_solid1, body_solid, 0, G4ThreeVector(0.0, 0.0, 9.8*CLHEP::cm)); + + G4LogicalVolume *inner_encapsulation_log = + new G4LogicalVolume(inner_encapsulation_solid, // G4VSolid + fParams.front_encapsulation_material, // G4Material + "inner_encapsulation_log"); + +/* G4VSolid *front_encapsulation_solid1 = + new G4Sphere("front_encapsulation_solid", + (enc_radius)*CLHEP::cm, // rmin 20 cm + (enc_radius+ enc_thickness) * CLHEP::cm, // rmax: 20.8 cm + 0.5 * CLHEP::pi, CLHEP::twopi, // phi + 0., 0.5 * CLHEP::pi); // theta + + G4VSolid *front_encapsulation_solid = new G4UnionSolid("front_encapsulation_solid", inner_encapsulation_solid, front_encapsulation_solid1); +*/ + + //front_encapsulation_solid = new G4SubtractionSolid("front_encapsulation_solid", front_encapsulation_solid, body_solid, 0, G4ThreeVector(0.0, 0.0, 9.8*CLHEP::cm)); + G4VSolid *optical_gel_encapsulation_solid = 0;//, in_encapsulation_solid = 0; + optical_gel_encapsulation_solid = optical_gel_pmt_subtraction(prefix + "_optical_gel_encapsulation_solid", body_solid); + + G4LogicalVolume *optical_gel_encapsulation_log = + new G4LogicalVolume(optical_gel_encapsulation_solid, // G4VSolid + fParams.optical_gel_material, // + "optical_gel_encapsulation_log"); + + G4Sphere *in_encapsulation_solid = + new G4Sphere("in_encapsulation_solid", + (0)*CLHEP::cm, // rmin 20 cm + (enc_radius) * CLHEP::cm, // rmax: 20.8 cm + 0.0, + CLHEP::twopi, 0.0, CLHEP::twopi); // theta + + G4LogicalVolume *in_encapsulation_log = + new G4LogicalVolume(in_encapsulation_solid, // G4VSolid + fParams.in_encapsulation_material, // G4Material + "in_encapsulation_log"); + + + /*G4Sphere *optical_gel_encapsulation_solid = + new G4Sphere("optical_gel_encapsulation_solid", + (enc_radius+enc_thickness)*CLHEP::cm, // rmin 20 cm + 5 * CLHEP::cm, // rmax: 20.8 cm + 0.5 * CLHEP::pi, CLHEP::twopi, // phi + 0., 0.5 * CLHEP::pi); + + */ + // theta, // G4Material + + + + + G4Sphere *front_encapsulation_solid = + new G4Sphere("front_encapsulation_solid", + (enc_radius)*CLHEP::cm, // rmin 20 cm + (enc_radius + enc_thickness) * CLHEP::cm, // rmax: 20.8 cm + 0.5 * CLHEP::pi, CLHEP::twopi, // phi + 0., 0.5 * CLHEP::pi); // theta + G4LogicalVolume *front_encapsulation_log = + new G4LogicalVolume(front_encapsulation_solid, // G4VSolid + fParams.front_encapsulation_material, // G4Material + "front_encapsulation_log"); + G4Sphere *rear_encapsulation_solid = + new G4Sphere("rear_encapsulation_solid", + (enc_radius)*CLHEP::cm, // rmin 20 cm + (enc_radius + enc_thickness) * CLHEP::cm, // rmax: 20.8 cm + 0.5 * CLHEP::pi, CLHEP::twopi, // phi + 0.5 * CLHEP::pi, 0.5 * CLHEP::pi); // theta + G4LogicalVolume *rear_encapsulation_log = + new G4LogicalVolume(rear_encapsulation_solid, // G4VSolid + fParams.rear_encapsulation_material, // G4Material + "rear_encapsulation_log"); + + G4Tubs *front_metal_flange_solid = new G4Tubs("front_metal_flange_solid", + 21.0 * CLHEP::cm, // rmin + 25.3 * CLHEP::cm, // rmax + 0.4 * CLHEP::cm, // size z + 0, CLHEP::twopi); // phi + G4LogicalVolume *front_metal_flange_encapsulation_log = + new G4LogicalVolume(front_metal_flange_solid, // G4VSolid + fParams.metal_flange_material, // G4Material + "front_metal_flange_encapsulation_log"); + + G4Tubs *rear_metal_flange_solid = new G4Tubs("rear_metal_flange_solid", + 21.0 * CLHEP::cm, // rmin + 25.3 * CLHEP::cm, // rmax + 0.4 * CLHEP::cm, // size z + 0, CLHEP::twopi); // phi + G4LogicalVolume *rear_metal_flange_encapsulation_log = + new G4LogicalVolume(rear_metal_flange_solid, // G4VSolid + fParams.metal_flange_material, // G4Material + "rear_metal_flange_encapsulation_log"); + + G4Tubs *acrylic_flange_solid = new G4Tubs("acrylic_flange_solid", + 20.8 * CLHEP::cm, // rmin + 25.3 * CLHEP::cm, // rmax + 0.7 * CLHEP::cm, // size z + 0, CLHEP::twopi); // phi + G4LogicalVolume *acrylic_flange_encapsulation_log = + new G4LogicalVolume(acrylic_flange_solid, // G4VSolid + fParams.acrylic_flange_material, // G4Material + "acrylic_flange_encapsulation_log"); + G4Box *silica_bag_solid = + new G4Box("silica_bag_solid", 18 * CLHEP::mm, 33 * CLHEP::mm, + 3 * CLHEP::mm); // zhalf + G4LogicalVolume *silica_bag_encapsulation_log = + new G4LogicalVolume(silica_bag_solid, // G4VSolid + fParams.silica_bag_material, // G4Materil + "silica_bag_encapsulation_log"); + G4Tubs *cable_solid = new G4Tubs("cable_solid", + 0 * CLHEP::cm, // rmin + 6.5 * CLHEP::mm, // rmax + 4.5 * CLHEP::cm, // size z + 0, CLHEP::twopi); // phi + G4LogicalVolume *cable_encapsulation_log = + new G4LogicalVolume(cable_solid, // G4VSolid + fParams.cable_material, // G4Material + "cable_encapsulation_log"); + + // ------------ Physical Volumes ------------- + G4ThreeVector noTranslation(0., 0., 0.); + body_phys = 0; + + if (fParams.useEnvelope) { + // place body in envelope + // this will set the pmt that triggers + /* body_phys = new G4PVPlacement( + 0, // no rotation + G4ThreeVector(0.0, 0.0, + 9.8 * CLHEP::cm), // Bounding envelope already constructed to put equator + // at origin + body_log, // the logical volume + prefix + "_body_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0); // copy number*/ + } + in_encapsulation_phys = new G4PVPlacement( + 0, // no rotation + G4ThreeVector(0.0, 0. * CLHEP::cm, + 0.0 * CLHEP::cm), // Bounding envelope already constructed + // to put equator at origin + in_encapsulation_log, // the logical volume + prefix + "in_encapsulation_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0); + body_phys = new G4PVPlacement( /// This subtracts the pmt from the in encapsulation volume + 0, // no rotation + G4ThreeVector(0.0, 0.0, + 9.8 * CLHEP::cm), // Bounding envelope already constructed to put equator + // at origin + body_log, // the logical volume + prefix + "_body_phys", // a name for this physical volume + in_encapsulation_log, // the mother volume + false, // no boolean ops + 0); // copy number + optical_gel_encapsulation_phys = new G4PVPlacement( + 0, // no rotation + G4ThreeVector(0.0, 0. * CLHEP::cm, + 0.0 * CLHEP::cm), // Bounding envelope already constructed + // to put equator at origin + optical_gel_encapsulation_log, // the logical volume + prefix + "in_encapsulation_phys", // a name for this physical volume + in_encapsulation_log, // the mother volume + false, // no boolean ops + 0); + + front_encapsulation_phys = new G4PVPlacement( + 0, // no rotation + G4ThreeVector(0.0, 0.0, + 0.0 * CLHEP::cm), // Bounding envelope already constructed + // to put equator at origin + front_encapsulation_log, // the logical volume + prefix + "_encapsulation_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0); // copy number + rear_encapsulation_phys = new G4PVPlacement( + 0, // no rotation + G4ThreeVector(0.0, 0.0, + 0.0 * CLHEP::cm), // Bounding envelope already constructed + // to put equator at origin + rear_encapsulation_log, // the logical volume + prefix + "_encapsulation_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0); // copy number + front_metal_encapsulaion_flange_phys = new G4PVPlacement( + 0, // no rotation + G4ThreeVector(0.0, 0.0, + 2. * CLHEP::cm), // Bounding envelope already constructed + // to put equator at origin + front_metal_flange_encapsulation_log, // the logical volume + prefix + "_encapsulation_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0); // copy number + rear_metal_encapsulation_flange_phys = new G4PVPlacement( + 0, // no rotation + G4ThreeVector(0.0, 0.0, + -0.2 * CLHEP::cm), // Bounding envelope already constructed + // to put equator at origin + rear_metal_flange_encapsulation_log, // the logical volume + prefix + "_encapsulation_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0); // copy number + acrylic_flange_encapsulaion_phys = new G4PVPlacement( + 0, // no rotation + G4ThreeVector(1.0, 1.0, + 0.8 * CLHEP::cm), // Bounding envelope already constructed + // to put equator at origin + acrylic_flange_encapsulation_log, // the logical volume + prefix + "_encapsulation_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0); + silica_bag_encapsulation_phys = new G4PVPlacement( + 0, // no rotation + G4ThreeVector(0.0, 13.5 * CLHEP::cm, + -7.4 * CLHEP::cm), // Bounding envelope already constructed + // to put equator at origin + silica_bag_encapsulation_log, // the logical volume + prefix + "_encapsulation_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0); + + /*silica_bag_encapsulation_phys2 = new G4PVPlacement( + 0, // no rotation + G4ThreeVector(0.0, -13.5 * CLHEP::cm, + 7.4 * CLHEP::cm), // Bounding envelope already constructed + // to put equator at origin + silica_bag_encapsulation_log, // the logical volume + prefix + "_encapsulation_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0);*/ + + cable_encapsulation_phys = new G4PVPlacement( + 0, // no rotation + G4ThreeVector(0.0, 0.0, + -15.2 * CLHEP::cm), // Bounding envelope already constructed + // to put equator at origin + cable_encapsulation_log, // the logical volume + prefix + "_encapsulation_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0); + + // place inner solids in outer solid (vacuum) + inner1_phys = new G4PVPlacement( + 0, // no rotation + G4ThreeVector(0.0, 0.0, 2. * hhgap), // puts face equator in right place, + // in front of tolerance gap + inner1_log, // the logical volume + prefix + "_inner1_phys", // a name for this physical volume + body_log, // the mother volume + false, // no boolean ops + 0); // copy number + + inner2_phys = new G4PVPlacement( + 0, // no rotation + noTranslation, // puts face equator in right place, behind the tolerance + // gap + inner2_log, // the logical volume + prefix + "_inner2_phys", // a name for this physical volume + body_log, // the mother volume + false, // no boolean ops + 0); // copy number + + // place gap between inner1 and inner2 + central_gap_phys = new G4PVPlacement( + 0, // no rotation + G4ThreeVector( + 0.0, 0.0, + hhgap), // puts face equator in right place, between inner1 and inner2 + central_gap_log, // the logical volume + prefix + "_central_gap_phys", // a name for this physical volume + body_log, // the mother volume + false, // no boolean ops + 0); // copy number + + // place dynode in stem/back + dynode_phys = new G4PVPlacement( + 0, G4ThreeVector(0.0, 0.0, fParams.dynodeTop - hhDynode), + prefix + "_dynode_phys", dynode_log, inner2_phys, false, 0); + + /// Encapsulation + // G4RotationMatrix* pmtrot = new G4RotationMatrix(); + // pmtrot->rotateY(angle_y); + // pmtrot->rotateX(angle_x); + // G4ThreeVector offsetfrontencapsulation = G4ThreeVector(0.0, 0.0, + // 0.8*CLHEP::cm); G4ThreeVector offsetfrontencapsulation_rot = + // pmtrot->inverse()(offsetfrontencapsulation); + // G4ThreeVector frontencapsulationpos = pmtpos + offsetacrylicflange_rot + + // offsetfrontencapsulation_rot; + + // build the optical surface for the dynode straight away since we already + // have the logical volume + new G4LogicalSkinSurface(prefix + "_dynode_logsurf", dynode_log, + fParams.dynode_surface); + + // Add the encapsulation surfaces + new G4LogicalSkinSurface( + "in_encapsulation_skin", + in_encapsulation_log, // Logical Volume + fParams.in_encapsulation_surface); // Surface Property + new G4LogicalSkinSurface( + "optical_gel_encapsulation_skin", + optical_gel_encapsulation_log, // Logical Volume + fParams.optical_gel_surface); // Surface Property + new G4LogicalSkinSurface( + "front_encapsulation_skin", + front_encapsulation_log, // Logical Volume + fParams.front_encapsulation_surface); // Surface Property + new G4LogicalSkinSurface( + "rear_encapsulation_skin", + rear_encapsulation_log, // Logical Volume + fParams.rear_encapsulation_surface); // Surface Property + new G4LogicalSkinSurface( + "front_metal_flange_encapsulation_skin", + front_metal_flange_encapsulation_log, /// Logical Volume + fParams.metal_flange_surface); // Surface Property + new G4LogicalSkinSurface( + "rear_metal_flange_encapsulation_skin", + rear_metal_flange_encapsulation_log, /// Logical Volume + fParams.metal_flange_surface); // Surface Property + new G4LogicalSkinSurface("acrylic_flange_encapsulation_skin", + acrylic_flange_encapsulation_log, /// Logical Volume + fParams.acrylic_flange_surface); // Surface Property + new G4LogicalSkinSurface("cable_encapsulation_skin", + cable_encapsulation_log, /// Logical Volume + fParams.cable_surface); // Surface Property + new G4LogicalSkinSurface("silica_bag_encapsulation_skin", + silica_bag_encapsulation_log, /// Logical Volume + fParams.silica_bag_surface); // Surface Property + + //--------------Exterior Optical Surface----------------- + // If we're using an envelope, body_phys has been created and we can therefore + // set the optical surfaces, otherwise this must be done later once the + // physical volume has been placed + if (fParams.useEnvelope) { + // build the mirrored surface + new G4LogicalBorderSurface(prefix + "_mirror_logsurf1", inner2_phys, + body_phys, fParams.mirror); + new G4LogicalBorderSurface(prefix + "_mirror_logsurf2", body_phys, + inner2_phys, fParams.mirror); + + // also include the tolerance gap + new G4LogicalBorderSurface(prefix + "_central_gap_logsurf1", + central_gap_phys, body_phys, fParams.mirror); + new G4LogicalBorderSurface(prefix + "_central_gap_logsurf2", body_phys, + central_gap_phys, fParams.mirror); + + // photocathode surface + new G4LogicalBorderSurface(prefix + "_photocathode_logsurf1", inner1_phys, + body_phys, fParams.photocathode); + + //encapsulation surface + new G4LogicalBorderSurface(prefix + "_backencap_logsurf1", rear_encapsulation_phys, + envelope_phys, fParams.rear_encapsulation_surface); + } + + // FIXME if fParams.seEnvelope == false this can't be done yet... + // Go ahead and place the cathode optical surface---this can always be done at + // this point + // ------------ FastSimulationModel ------------- + // 28-Jul-2006 WGS: Must define a G4Region for Fast Simulations + // (change from Geant 4.7 to Geant 4.8). + G4Region *body_region = new G4Region(prefix + "_GLG4_PMTOpticalRegion"); + body_region->AddRootLogicalVolume(body_log); + /*GLG4PMTOpticalModel * pmtOpticalModel =*/ + new GLG4PMTOpticalModel( + prefix + "_optical_model", body_region, body_log, fParams.photocathode, + fParams.efficiencyCorrection, fParams.dynodeTop, fParams.dynodeRadius, + 0.0, /*prepusling handled after absorption*/ + fParams.photocathode_MINrho, fParams.photocathode_MAXrho); + + // ------------ Vis Attributes ------------- + G4VisAttributes *visAtt; + if (fParams.simpleVis) { + visAtt = new G4VisAttributes(G4Color(0.0, 1.0, 1.0, 0.05)); + if (fParams.useEnvelope) { + // envelope_log->SetVisAttributes(visAtt); + } + body_log->SetVisAttributes(G4VisAttributes::GetInvisible()); + dynode_log->SetVisAttributes(G4VisAttributes::GetInvisible()); + inner1_log->SetVisAttributes(G4VisAttributes::GetInvisible()); + inner2_log->SetVisAttributes(G4VisAttributes::GetInvisible()); + central_gap_log->SetVisAttributes(G4VisAttributes::GetInvisible()); + in_encapsulation_log->SetVisAttributes(G4VisAttributes::GetInvisible()); + optical_gel_encapsulation_log->SetVisAttributes(G4VisAttributes::GetInvisible()); + front_encapsulation_log->SetVisAttributes(G4VisAttributes::GetInvisible()); + rear_encapsulation_log->SetVisAttributes(G4VisAttributes::GetInvisible()); + front_metal_flange_encapsulation_log->SetVisAttributes( + G4VisAttributes::GetInvisible()); + rear_metal_flange_encapsulation_log->SetVisAttributes( + G4VisAttributes::GetInvisible()); + acrylic_flange_encapsulation_log->SetVisAttributes( + G4VisAttributes::GetInvisible()); + cable_encapsulation_log->SetVisAttributes(G4VisAttributes::GetInvisible()); + silica_bag_encapsulation_log->SetVisAttributes( + G4VisAttributes::GetInvisible()); + + } else { + if (fParams.useEnvelope) { + envelope_log->SetVisAttributes(G4VisAttributes::GetInvisible()); + //visAtt = new G4VisAttributes(G4Color(0.0, 1.0, 0.0, 1.0)); + //envelope_log->SetVisAttributes(visAtt); + } + // PMT glass + visAtt = new G4VisAttributes(G4Color(0.0, 1.0, 1.0, 0.05)); + body_log->SetVisAttributes(visAtt); + // dynode is medium gray + visAtt = new G4VisAttributes(G4Color(0.5, 0.5, 0.5, 1.0)); + dynode_log->SetVisAttributes(visAtt); + // (surface of) interior vacuum is clear orangish gray on top (PC), + // silvery blue on bottom (mirror) + visAtt = new G4VisAttributes(G4Color(0.7, 0.5, 0.3, 0.27)); + inner1_log->SetVisAttributes(visAtt); + visAtt = new G4VisAttributes(G4Color(0.6, 0.7, 0.8, 0.67)); + inner2_log->SetVisAttributes(visAtt); + // central gap is invisible + central_gap_log->SetVisAttributes(G4VisAttributes::GetInvisible()); + // set encap + visAtt = new G4VisAttributes(G4Color(0.77, 0.97, 1., 0.3)); + in_encapsulation_log->SetVisAttributes(visAtt); + visAtt = new G4VisAttributes(G4Color(0.87, 0.81, 0.11, 0.5)); + optical_gel_encapsulation_log->SetVisAttributes(visAtt); + visAtt = new G4VisAttributes(G4Color(0.44, 0.52, 0.78, 0.5)); + front_encapsulation_log->SetVisAttributes(visAtt); + acrylic_flange_encapsulation_log->SetVisAttributes(visAtt); + visAtt = new G4VisAttributes(G4Color(0., 0.03, 0.14, 1.)); + rear_encapsulation_log->SetVisAttributes(visAtt); + visAtt = new G4VisAttributes(G4Color(0.68, 0.68, 0.68, 1.0)); + front_metal_flange_encapsulation_log->SetVisAttributes(visAtt); + rear_metal_flange_encapsulation_log->SetVisAttributes(visAtt); + visAtt = new G4VisAttributes(G4Color(0.3, 0.1, 0.1, 1.0)); + silica_bag_encapsulation_log->SetVisAttributes(visAtt); + visAtt = new G4VisAttributes(G4Color(1.0, 0.18, 0.8, 1.0)); + cable_encapsulation_log->SetVisAttributes(visAtt); + } + + log_pmt = envelope_log;//body_log; + + // if using envelope place waveguide now + if (fParams.useEnvelope && fWaveguideFactory) { + fWaveguideFactory->SetPMTBodySolid(body_solid); + G4LogicalVolume *log_wg = fWaveguideFactory->Construct( + prefix + "_waveguide_log", log_pmt, fParams.simpleVis); + G4ThreeVector offsetWg = fWaveguideFactory->GetPlacementOffset(); + new G4PVPlacement(0, // no rotation + offsetWg, + log_wg, // the logical volume + prefix + + "_waveguide_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0); // copy number + } + + return log_pmt; +} + +G4VSolid *EncapsulatedPMTConstruction::BuildSolid(const std::string &_name) { + GLG4TorusStack *body = new GLG4TorusStack(_name); + body->SetAllParameters(fParams.zOrigin.size(), &fParams.zEdge[0], + &fParams.rhoEdge[0], &fParams.zOrigin[0]); + return body; +} + +G4PVPlacement *EncapsulatedPMTConstruction::PlacePMT( + G4RotationMatrix *pmtrot, G4ThreeVector pmtpos, const std::string &_name, + G4LogicalVolume *logi_pmt, G4VPhysicalVolume *mother_phys, + bool booleanSolid, int copyNo) { + if (fParams.useEnvelope) { + return new G4PVPlacement(pmtrot, pmtpos, _name, logi_pmt, mother_phys, + booleanSolid, copyNo); + } else { + encapsulation_phys = new G4PVPlacement(pmtrot, pmtpos, _name, logi_pmt, + mother_phys, booleanSolid, copyNo); + + body_phys = new G4PVPlacement(pmtrot, pmtpos, _name, logi_pmt, mother_phys, + booleanSolid, copyNo); + + // build the mirrored surface + new G4LogicalBorderSurface(_name + "_mirror_logsurf1", inner2_phys, + body_phys, fParams.mirror); + new G4LogicalBorderSurface(_name + "_mirror_logsurf2", body_phys, + inner2_phys, fParams.mirror); + + // also include the tolerance gap + new G4LogicalBorderSurface(_name + "_central_gap_logsurf1", + central_gap_phys, body_phys, fParams.mirror); + new G4LogicalBorderSurface(_name + "_central_gap_logsurf2", body_phys, + central_gap_phys, fParams.mirror); + + // photocathode surface + new G4LogicalBorderSurface(_name + "_photocathode_logsurf1", inner1_phys, + body_phys, fParams.photocathode); + + // if not using envelope place waveguide now + if (fWaveguideFactory) { + G4LogicalVolume *log_wg = fWaveguideFactory->Construct( + _name + "_waveguide_log", logi_pmt, fParams.simpleVis); + // pmtrot is a passive rotation, but we need an active one to put offsetWg + // into coordinates of mother + G4ThreeVector offsetWg = fWaveguideFactory->GetPlacementOffset(); + G4ThreeVector offsetWg_rot = pmtrot->inverse()(offsetWg); + G4ThreeVector waveguidepos = pmtpos + offsetWg_rot; + new G4PVPlacement(pmtrot, waveguidepos, + _name + "_waveguide", // a name for this physical volume + log_wg, // the logical volume + mother_phys, // the mother volume + false, // no boolean ops + 0); // copy number + } + return body_phys; + } +} + +G4VSolid * +EncapsulatedPMTConstruction::optical_gel_height_subtraction(const std::string &_name) { + + double enc_radius = 20.0; // default radius + double enc_thickness = 0.8; + G4Sphere *optical_gel_1 = + new G4Sphere("optical_gel_1_encapsulation_solid", + 15*CLHEP::cm,///(enc_radius-enc_thickness)*CLHEP::cm, // rmin 20 cm + 20.0*CLHEP::cm,// (enc_radius+enc_thickness)+5 * CLHEP::cm, // rmax: 20.8 cm + 0.5 * CLHEP::pi, CLHEP::twopi, // phi + 0., 0.5 * CLHEP::pi); + G4Tubs *gel_subtract = + new G4Tubs("gel_sub__solid", 0.0, + 25*CLHEP::cm, // solid cylinder (FIXME?) + 15*CLHEP::cm, // half height of cylinder + 0., CLHEP::twopi); // cylinder complete in phi + + return new G4SubtractionSolid(_name, optical_gel_1, gel_subtract, 0, G4ThreeVector(0.0, 0.0, 0.0*CLHEP::cm)); //8.5 + //return inner_encapsulation_solid2; +}// + + +G4VSolid * +EncapsulatedPMTConstruction::optical_gel_pmt_subtraction(const std::string &_name, GLG4TorusStack *body){ + + G4VSolid *optical_gel_2 = 0; + optical_gel_2 = optical_gel_height_subtraction("temp_gel"+ _name); + + + return new G4SubtractionSolid(_name, optical_gel_2, body, 0, G4ThreeVector(0.0, 0.0, 9.8*CLHEP::cm)); //8.5 + //return inner_encapsulation_solid2; +}// + +G4VSolid * +EncapsulatedPMTConstruction::NewEnvelopeSolid(const std::string &_name) { + /*G4double zTop = fParams.zEdge[0] + fParams.faceGap; + G4double zBottom = fParams.zEdge[fParams.zEdge.size() - 1]; + G4double rho = fParams.minEnvelopeRadius; + for (unsigned i = 0; i < fParams.rhoEdge.size(); i++) { + if (fParams.rhoEdge[i] > rho) { + rho = fParams.rhoEdge[i]; + } + } + + G4double mainCylHalfHeight = std::max(zTop, -zBottom); + G4double subCylHalfHeight = + (mainCylHalfHeight - std::min(zTop, -zBottom)) / 2.0; + G4double subCylOffset; + if (zTop < -zBottom) { + subCylOffset = zTop + subCylHalfHeight; + } else { + subCylOffset = zBottom - subCylHalfHeight; + } + + G4Tubs *mainEnvelope = new G4Tubs(_name + "_main", 0.0, rho, + mainCylHalfHeight, 0.0, CLHEP::twopi); + G4Tubs *subEnvelope = new G4Tubs(_name + "_sub", 0.0, rho * 1.1, + subCylHalfHeight, 0.0, CLHEP::twopi); + + return new G4SubtractionSolid(_name, mainEnvelope, subEnvelope, 0, + G4ThreeVector(0.0, 0.0, subCylOffset));*/ + + G4Sphere *outer_s = new G4Sphere(_name+ "_main", 0. * CLHEP::mm, 25.4*CLHEP::cm, 0.0, CLHEP::twopi, 0.0, CLHEP::twopi); + //G4Sphere *inner_s = new G4Sphere(_name+ "_sub", 0. * CLHEP::mm, 25.3*CLHEP::cm, 0.0, CLHEP::twopi, 0.0, CLHEP::twopi); + + //return new G4SubtractionSolid(_name, outer_s, inner_s); + return outer_s; +} + +void EncapsulatedPMTConstruction::CalcInnerParams( + GLG4TorusStack *body, std::vector &innerZEdge, + std::vector &innerRhoEdge, int &equatorIndex, + double &zLowestDynode) { + + ////// The encapsulation size is hard coded in to insure the correct size for + /// BUTTON encapsulation but it could be added here if different pmt sizes + /// were wanted! + + // Local references + const G4double wall = fParams.wallThickness; + const G4double dynodeRadius = fParams.dynodeRadius; + const std::vector &outerZEdge = fParams.zEdge; + const std::vector &outerRhoEdge = fParams.rhoEdge; + const int nEdge = fParams.zEdge.size() - 1; + + // set shapes of inner volumes, scan for lowest allowed point of dynode + zLowestDynode = fParams.dynodeTop; + innerZEdge.resize(fParams.zEdge.size()); + innerRhoEdge.resize(fParams.rhoEdge.size()); + + // We will have to calculate the inner dimensions of the PMT. + G4ThreeVector norm; + equatorIndex = -1; + + // calculate inner surface edges, check dynode position, and find equator + innerZEdge[0] = outerZEdge[0] - wall; + innerRhoEdge[0] = 0.0; + for (int i = 1; i < nEdge; i++) { + norm = + body->SurfaceNormal(G4ThreeVector(0.0, outerRhoEdge[i], outerZEdge[i])); + innerZEdge[i] = outerZEdge[i] - wall * norm.z(); + innerRhoEdge[i] = outerRhoEdge[i] - wall * norm.y(); + if (innerRhoEdge[i] > dynodeRadius && innerZEdge[i] < zLowestDynode) { + zLowestDynode = innerZEdge[i]; + } + if (outerZEdge[i] == 0.0 || innerZEdge[i] == 0.0) { + equatorIndex = i; + } + } + + innerZEdge[nEdge] = outerZEdge[nEdge] + wall; + innerRhoEdge[nEdge] = outerRhoEdge[nEdge] - wall; + + // one final check on dynode allowed position + if (innerRhoEdge[nEdge] > dynodeRadius && innerZEdge[nEdge] < zLowestDynode) { + zLowestDynode = innerZEdge[nEdge]; + } + + // sanity check equator index + if (equatorIndex < 0) { + Log::Die("EncapsulatedPMTConstruction::CalcInnerParams: Pathological PMT " + "shape with no equator edge"); + } + // sanity check on dynode height + if (fParams.dynodeTop > innerZEdge[equatorIndex]) { + Log::Die("EncapsulatedPMTConstruction::CalcInnerParams: Top of PMT dynode " + "cannot be higher than equator."); + } +} + +} // namespace RAT From 2df4412573a8acb29b728dc609e8a97903cd45a7 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Wed, 2 Apr 2025 00:46:14 +0100 Subject: [PATCH 03/52] updated for encapsulation --- src/geo/src/pmt/PMTFactoryBase.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/geo/src/pmt/PMTFactoryBase.cc b/src/geo/src/pmt/PMTFactoryBase.cc index 651f6e07..b0976b55 100644 --- a/src/geo/src/pmt/PMTFactoryBase.cc +++ b/src/geo/src/pmt/PMTFactoryBase.cc @@ -33,6 +33,7 @@ G4VPhysicalVolume *PMTFactoryBase::ConstructPMTs( std::string pmt_model = table->GetS("pmt_model"); DBLinkPtr lpmt = DB::Get()->GetLink("PMT", pmt_model); + std::string construction_type = lpmt->GetS("construction"); // Find mother volume G4LogicalVolume *mother = FindMother(mother_name); @@ -363,8 +364,13 @@ G4VPhysicalVolume *PMTFactoryBase::ConstructPMTs( const G4String modname(volume_name + "_optical_model"); // In case the main pmt volume doesn't correspond to the fastsim region G4LogicalVolume *fastsim_log_pmt = log_pmt; + G4LogicalVolume *fastsim_log_pmt_dau = 0; if (fastsim_log_pmt->GetFastSimulationManager() == NULL) { - fastsim_log_pmt = log_pmt->GetDaughter(0)->GetLogicalVolume(); // Get the glass region + if (construction_type == "encapsulated") { + fastsim_log_pmt_dau = log_pmt->GetDaughter(0)->GetLogicalVolume(); + fastsim_log_pmt = fastsim_log_pmt_dau->GetDaughter(0)->GetLogicalVolume(); // Get the glass region + } + else fastsim_log_pmt = log_pmt->GetDaughter(0)->GetLogicalVolume(); } for (size_t i = 0; i < fastsim_log_pmt->GetFastSimulationManager()->GetFastSimulationModelList().size(); i++) { From 5a88089456a1d9d68c067f9d11b412b6ea860f10 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Wed, 2 Apr 2025 00:47:55 +0100 Subject: [PATCH 04/52] updated for encapsulation --- .../RAT/EncapsulatedPMTConstruction.hh | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 src/geo/include/RAT/EncapsulatedPMTConstruction.hh diff --git a/src/geo/include/RAT/EncapsulatedPMTConstruction.hh b/src/geo/include/RAT/EncapsulatedPMTConstruction.hh new file mode 100644 index 00000000..c3096d40 --- /dev/null +++ b/src/geo/include/RAT/EncapsulatedPMTConstruction.hh @@ -0,0 +1,140 @@ +// Adam T: A encapsulat// Adam T: A encapsulated pmt based off the Toroidal pmt construction model for +// button (some of the offesets will need adjusted for different pmt this will +// work for the r7081pe model) +#ifndef __RAT_EncapsulatedPMTConstruction__ +#define __RAT_EncapsulatedPMTConstruction__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +namespace RAT { + +struct EncapsulatedPMTConstructionParams { + EncapsulatedPMTConstructionParams() { + efficiencyCorrection = 1.0; + simpleVis = false; + photocathode_MINrho = 0.0; + photocathode_MAXrho = 0.0; + }; + + bool simpleVis; + + // Envelope control + bool useEnvelope; + double faceGap; + double minEnvelopeRadius; + + // Body + std::vector zEdge; // n+1 + std::vector rhoEdge; // n+1 + std::vector zOrigin; // n + double wallThickness; // mm + + double dynodeRadius; // mm + double dynodeTop; // mm + double photocathode_MINrho; // mm + double photocathode_MAXrho; // mm + + G4Material *exterior; + G4Material *glass; + G4Material *vacuum; + G4Material *dynode; + + G4OpticalSurface *photocathode; + G4OpticalSurface *mirror; + G4OpticalSurface *dynode_surface; + + // Encapsulation + G4Material *in_encapsulation_material; + G4Material *front_encapsulation_material; + G4Material *rear_encapsulation_material; + G4Material *metal_flange_material; + G4Material *acrylic_flange_material; + G4Material *silica_bag_material; + G4Material *cable_material; + G4Material *optical_gel_material; + + G4OpticalSurface *in_encapsulation_surface; + G4OpticalSurface *front_encapsulation_surface; + G4OpticalSurface *rear_encapsulation_surface; + G4OpticalSurface *metal_flange_surface; + G4OpticalSurface *acrylic_flange_surface; + G4OpticalSurface *cable_surface; + G4OpticalSurface *silica_bag_surface; + G4OpticalSurface *optical_gel_surface; + + double efficiencyCorrection; // default to 1.0 for no correction +}; + +// Construction for PMTs based on GLG4TorusStack +class EncapsulatedPMTConstruction : public PMTConstruction { +public: + EncapsulatedPMTConstruction(DBLinkPtr params, G4LogicalVolume *mother); + virtual ~EncapsulatedPMTConstruction() {} + + virtual G4LogicalVolume *BuildVolume(const std::string &prefix); + virtual G4VSolid *BuildSolid(const std::string &prefix); + virtual G4PVPlacement *PlacePMT(G4RotationMatrix *pmtrot, + G4ThreeVector pmtpos, const std::string &name, + G4LogicalVolume *logi_pmt, + G4VPhysicalVolume *mother_phys, + bool booleanSolid, int copyNo); + +protected: + G4VSolid *NewEnvelopeSolid(const std::string &name); + G4VSolid *NewEncapsulationSolid(const std::string &name); + G4VSolid *optical_gel_height_subtraction(const std::string &_name); + G4VSolid *optical_gel_pmt_subtraction(const std::string &_name, GLG4TorusStack *body); + void CalcInnerParams(GLG4TorusStack *body, std::vector &innerZEdge, + std::vector &innerRhoEdge, int &equatorIndex, + double &zLowestDynode); + + // phyiscal volumes + G4PVPlacement *envelope_phys; + G4PVPlacement *body_phys; + G4PVPlacement *inner1_phys; + G4PVPlacement *inner2_phys; + G4PVPlacement *central_gap_phys; + G4PVPlacement *dynode_phys; + + ///// Encapsulation + G4PVPlacement *in_encapsulation_phys; + G4PVPlacement *optical_gel_encapsulation_phys; + G4PVPlacement *encapsulation_phys; + G4PVPlacement *front_encapsulation_phys; + G4PVPlacement *rear_encapsulation_phys = 0; + G4PVPlacement *front_metal_encapsulaion_flange_phys; + G4PVPlacement *rear_metal_encapsulation_flange_phys; + G4PVPlacement *acrylic_flange_encapsulaion_phys; + G4PVPlacement *silica_bag_encapsulation_phys; + G4PVPlacement *silica_bag_encapsulation_phys2; + G4PVPlacement *cable_encapsulation_phys; + + G4LogicalVolume *log_pmt; + + WaveguideFactory *fWaveguideFactory; + + EncapsulatedPMTConstructionParams fParams; +}; + +} // namespace RAT + +#endif From b14a2b7956d16e313c6d6be7c3b3fd347f363dfc Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Wed, 2 Apr 2025 00:48:58 +0100 Subject: [PATCH 05/52] updated for encapsulation --- src/geo/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/geo/CMakeLists.txt b/src/geo/CMakeLists.txt index 9ff8b24f..f2c7ae07 100644 --- a/src/geo/CMakeLists.txt +++ b/src/geo/CMakeLists.txt @@ -64,6 +64,7 @@ add_library(geo OBJECT src/pmt/RevolutionPMTConstruction.cc src/pmt/ToroidalPMTConstruction.cc src/pmt/CylindricalPMTConstruction.cc + src/pmt/EncapsulatedPMTConstruction.cc ) # Set our include directories From a255a2a25cc7c43a23073c01596aae6286a1122f Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Wed, 2 Apr 2025 00:51:52 +0100 Subject: [PATCH 06/52] updated for encapsulation --- src/geo/src/pmt/PMTConstruction.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/geo/src/pmt/PMTConstruction.cc b/src/geo/src/pmt/PMTConstruction.cc index d886ad81..cce29d7d 100644 --- a/src/geo/src/pmt/PMTConstruction.cc +++ b/src/geo/src/pmt/PMTConstruction.cc @@ -13,6 +13,7 @@ #include #include #include +#include #include namespace RAT { From 75c8a9f535621640f8e083725112ed66c6596b1a Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Tue, 15 Apr 2025 15:21:29 +0100 Subject: [PATCH 07/52] Tidied up code to ready for pull request --- .../src/pmt/EncapsulatedPMTConstruction.cc | 335 ++++++------------ src/geo/src/pmt/PMTFactoryBase.cc | 4 +- 2 files changed, 105 insertions(+), 234 deletions(-) diff --git a/src/geo/src/pmt/EncapsulatedPMTConstruction.cc b/src/geo/src/pmt/EncapsulatedPMTConstruction.cc index fcf8b192..4bb6e4c6 100644 --- a/src/geo/src/pmt/EncapsulatedPMTConstruction.cc +++ b/src/geo/src/pmt/EncapsulatedPMTConstruction.cc @@ -1,6 +1,6 @@ -// Adam T: A encapsulated pmt based off the Toroidal pmt construction model for -// button (some of the offesets will need adjusted for different pmt this will -// work for the r7081pe model) +// This is a modified version of ToroidalPMTConstruction.cc, which encapsulates a toroidal PMT. +// It is intended to be used for BUTTON which uses 96 Hamamatsu r7081pe PMTs that are encapsulated by two acryilic domes. +// Created by Lewis Sexton (Sheffield) and Adam Tarrant (Liverpool) #include @@ -66,7 +66,7 @@ EncapsulatedPMTConstruction::EncapsulatedPMTConstruction( } catch (DBNotFoundError &e) { }; - // Materials + // PMT Materials fParams.exterior = mother->GetMaterial(); fParams.glass = G4Material::GetMaterial(table->GetS("glass_material")); fParams.dynode = G4Material::GetMaterial(table->GetS("dynode_material")); @@ -78,7 +78,7 @@ EncapsulatedPMTConstruction::EncapsulatedPMTConstruction( fParams.dynode_surface = Materials::optical_surface[table->GetS("dynode_surface")]; - // Encapsulation + // Encapsulation materials fParams.in_encapsulation_material = G4Material::GetMaterial(table->GetS("inside_encapsulation_material")); fParams.front_encapsulation_material = @@ -113,37 +113,6 @@ EncapsulatedPMTConstruction::EncapsulatedPMTConstruction( fParams.optical_gel_surface = Materials::optical_surface[table->GetS("optical_gel_material")]; - - - /* - - fParams.front_encapsulation_material = - G4Material::GetMaterial(table->GetS("front_encapsulation_material")); - fParams.rear_encapsulation_material = - G4Material::GetMaterial(table->GetS("rear_encapsulation_material")); - fParams.metal_flange_material = - G4Material::GetMaterial(table->GetS("metal_flange_material")); - fParams.acrylic_flange_material = - G4Material::GetMaterial(table->GetS("acrylic_flange_material")); - fParams.silica_bag_material = - G4Material::GetMaterial(table->GetS("silica_bag_material")); - fParams.cable_material = - G4Material::GetMaterial(table->GetS("cable_material")); - - fParams.front_encapsulation_surface = - Materials::optical_surface[table->GetS("front_encapsultion_material")]; - fParams.rear_encapsulation_surface = - Materials::optical_surface[table->GetS("rear_encapsulation_material")]; - fParams.metal_flange_surface = - Materials::optical_surface[table->GetS("metal_flange_material")]; - fParams.acrylic_flange_surface = - Materials::optical_surface[table->GetS("acrylic_flange_material")]; - fParams.silica_bag_surface = - Materials::optical_surface[table->GetS("silica_bag_material")]; - fParams.cable_surface = - Materials::optical_surface[table->GetS("cable_material")]; - */ - if (fParams.photocathode == 0) { Log::Die("EncapsulatedPMTConstruction error: Photocathode surface \"" + pc_surface_name + "\" not found"); @@ -195,6 +164,8 @@ EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { if (log_pmt) { return log_pmt; } + + // Generate PMT solids // envelope cylinder G4VSolid *envelope_solid = 0; @@ -242,7 +213,61 @@ EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { toleranceGapRadius, // solid cylinder with same radius as PMT hhgap, // half height of cylinder 0., CLHEP::twopi); // cylinder complete in phi + + // Generate Encapsulation solids + double enc_radius = 20.0; // default radius + double enc_thickness = 0.8; // 8mm encapsulation thickness + + G4VSolid *optical_gel_encapsulation_solid = 0; + optical_gel_encapsulation_solid = optical_gel_pmt_subtraction(prefix + "_optical_gel_encapsulation_solid", body_solid); + + G4Sphere *in_encapsulation_solid = + new G4Sphere("in_encapsulation_solid", + (0)*CLHEP::cm, // rmin 20 cm + (enc_radius) * CLHEP::cm, // rmax: 20.8 cm + 0.0, // phi + CLHEP::twopi, 0.0, CLHEP::twopi); // theta + + G4Sphere *front_encapsulation_solid = + new G4Sphere("front_encapsulation_solid", + (enc_radius)*CLHEP::cm, // rmin 20 cm + (enc_radius + enc_thickness) * CLHEP::cm, // rmax: 20.8 cm + 0.5 * CLHEP::pi, CLHEP::twopi, // phi + 0., 0.5 * CLHEP::pi); // theta + + G4Sphere *rear_encapsulation_solid = + new G4Sphere("rear_encapsulation_solid", + (enc_radius)*CLHEP::cm, // rmin 20 cm + (enc_radius + enc_thickness) * CLHEP::cm, // rmax: 20.8 cm + 0.5 * CLHEP::pi, CLHEP::twopi, // phi + 0.5 * CLHEP::pi, 0.5 * CLHEP::pi); // theta + G4Tubs *front_metal_flange_solid = new G4Tubs("front_metal_flange_solid", + 21.0 * CLHEP::cm, // rmin + 25.3 * CLHEP::cm, // rmax + 0.4 * CLHEP::cm, // size z + 0, CLHEP::twopi); // phi + + G4Tubs *rear_metal_flange_solid = new G4Tubs("rear_metal_flange_solid", + 21.0 * CLHEP::cm, // rmin + 25.3 * CLHEP::cm, // rmax + 0.4 * CLHEP::cm, // size z + 0, CLHEP::twopi); // phi + + G4Tubs *acrylic_flange_solid = new G4Tubs("acrylic_flange_solid", + 20.8 * CLHEP::cm, // rmin + 25.3 * CLHEP::cm, // rmax + 0.7 * CLHEP::cm, // size z + 0, CLHEP::twopi); // phi + + G4Box *silica_bag_solid = new G4Box("silica_bag_solid", 18 * CLHEP::mm, 33 * CLHEP::mm, 3 * CLHEP::mm); // zhalf + + G4Tubs *cable_solid = new G4Tubs("cable_solid", + 0 * CLHEP::cm, // rmin + 6.5 * CLHEP::mm, // rmax + 4.5 * CLHEP::cm, // size z + 0, CLHEP::twopi); // phi + // ------------ Logical Volumes ------------- G4LogicalVolume *envelope_log = 0, *body_log, *inner1_log, *inner2_log, *dynode_log, *central_gap_log; @@ -251,7 +276,8 @@ EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { envelope_log = new G4LogicalVolume(envelope_solid, fParams.exterior, prefix + "_envelope_log"); } - + + // PMT logical volumes body_log = new G4LogicalVolume(body_solid, fParams.glass, prefix + "_body_log"); @@ -267,152 +293,47 @@ EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { central_gap_log = new G4LogicalVolume(central_gap_solid, fParams.vacuum, prefix + "_central_gap_log"); - ///// Encapsulaiton - // The default inner encapsulation diameter is: 40cm - // front and back perpendicular to the PMT direction - // rotation required to point in direction of pmtdir - // double angle_y = (-1.0)*atan2(pmtdir.x(), pmtdir.z()); - // double angle_x = atan2(pmtdir.y(), - // sqrt(pmtdir.x()*pmtdir.x()+pmtdir.z()*pmtdir.z())); - - // G4RotationMatrix* pmtrot = new G4RotationMatrix(); - // pmtrot->rotateY(angle_y); - // pmtrot->rotateX(angle_x);.. - - // fParams.front_encapsulation_material = - // G4Material::GetMaterial("nakano_acrylic"); - // fParams.front_encapsulation_surface = - // Materials::optical_surface[table->GetS("nakano_acrylic")]; - G4cout << "PMT encapsulation is added!! \n "; - double enc_radius = 20.0; // default radius - double enc_thickness = 0.8; // 8mm encapsulation thickness - -/* G4VSolid *inner_encapsulation_solid = 0; - inner_encapsulation_solid = optical_gel(prefix + "_inner_encapsulation_solid", body_solid); - inner_encapsulation_log = new G4LogicalVolume(inner_encapsulation_solid, // G4VSolid - fParams.front_encapsulation_material, // G4Material - prefix+"inner_encapsulation_log"); - - G4VSolid *inner_encapsulation_solid = - new G4Sphere("inner_encapsulation_solid", - (0.0)*CLHEP::cm, // rmin 20 cm - (enc_radius-0.001) * CLHEP::cm, // rmax: 20.8 cm - CLHEP::pi, CLHEP::twopi, // phi - 0., CLHEP::pi); // theta - //G4VSolid *inner_encapsulation_solid = new G4SubtractionSolid("inner_encapsulation_solid", inner_encapsulation_solid1, body_solid, 0, G4ThreeVector(0.0, 0.0, 9.8*CLHEP::cm)); - - G4LogicalVolume *inner_encapsulation_log = - new G4LogicalVolume(inner_encapsulation_solid, // G4VSolid - fParams.front_encapsulation_material, // G4Material - "inner_encapsulation_log"); - -/* G4VSolid *front_encapsulation_solid1 = - new G4Sphere("front_encapsulation_solid", - (enc_radius)*CLHEP::cm, // rmin 20 cm - (enc_radius+ enc_thickness) * CLHEP::cm, // rmax: 20.8 cm - 0.5 * CLHEP::pi, CLHEP::twopi, // phi - 0., 0.5 * CLHEP::pi); // theta - - G4VSolid *front_encapsulation_solid = new G4UnionSolid("front_encapsulation_solid", inner_encapsulation_solid, front_encapsulation_solid1); -*/ - - //front_encapsulation_solid = new G4SubtractionSolid("front_encapsulation_solid", front_encapsulation_solid, body_solid, 0, G4ThreeVector(0.0, 0.0, 9.8*CLHEP::cm)); - G4VSolid *optical_gel_encapsulation_solid = 0;//, in_encapsulation_solid = 0; - optical_gel_encapsulation_solid = optical_gel_pmt_subtraction(prefix + "_optical_gel_encapsulation_solid", body_solid); - + // Encapsulaiton logical volumes G4LogicalVolume *optical_gel_encapsulation_log = new G4LogicalVolume(optical_gel_encapsulation_solid, // G4VSolid fParams.optical_gel_material, // "optical_gel_encapsulation_log"); - G4Sphere *in_encapsulation_solid = - new G4Sphere("in_encapsulation_solid", - (0)*CLHEP::cm, // rmin 20 cm - (enc_radius) * CLHEP::cm, // rmax: 20.8 cm - 0.0, - CLHEP::twopi, 0.0, CLHEP::twopi); // theta - G4LogicalVolume *in_encapsulation_log = new G4LogicalVolume(in_encapsulation_solid, // G4VSolid fParams.in_encapsulation_material, // G4Material "in_encapsulation_log"); - - /*G4Sphere *optical_gel_encapsulation_solid = - new G4Sphere("optical_gel_encapsulation_solid", - (enc_radius+enc_thickness)*CLHEP::cm, // rmin 20 cm - 5 * CLHEP::cm, // rmax: 20.8 cm - 0.5 * CLHEP::pi, CLHEP::twopi, // phi - 0., 0.5 * CLHEP::pi); - - */ - // theta, // G4Material - - - - - G4Sphere *front_encapsulation_solid = - new G4Sphere("front_encapsulation_solid", - (enc_radius)*CLHEP::cm, // rmin 20 cm - (enc_radius + enc_thickness) * CLHEP::cm, // rmax: 20.8 cm - 0.5 * CLHEP::pi, CLHEP::twopi, // phi - 0., 0.5 * CLHEP::pi); // theta G4LogicalVolume *front_encapsulation_log = new G4LogicalVolume(front_encapsulation_solid, // G4VSolid fParams.front_encapsulation_material, // G4Material "front_encapsulation_log"); - G4Sphere *rear_encapsulation_solid = - new G4Sphere("rear_encapsulation_solid", - (enc_radius)*CLHEP::cm, // rmin 20 cm - (enc_radius + enc_thickness) * CLHEP::cm, // rmax: 20.8 cm - 0.5 * CLHEP::pi, CLHEP::twopi, // phi - 0.5 * CLHEP::pi, 0.5 * CLHEP::pi); // theta + G4LogicalVolume *rear_encapsulation_log = new G4LogicalVolume(rear_encapsulation_solid, // G4VSolid fParams.rear_encapsulation_material, // G4Material "rear_encapsulation_log"); - - G4Tubs *front_metal_flange_solid = new G4Tubs("front_metal_flange_solid", - 21.0 * CLHEP::cm, // rmin - 25.3 * CLHEP::cm, // rmax - 0.4 * CLHEP::cm, // size z - 0, CLHEP::twopi); // phi + G4LogicalVolume *front_metal_flange_encapsulation_log = new G4LogicalVolume(front_metal_flange_solid, // G4VSolid fParams.metal_flange_material, // G4Material "front_metal_flange_encapsulation_log"); - G4Tubs *rear_metal_flange_solid = new G4Tubs("rear_metal_flange_solid", - 21.0 * CLHEP::cm, // rmin - 25.3 * CLHEP::cm, // rmax - 0.4 * CLHEP::cm, // size z - 0, CLHEP::twopi); // phi G4LogicalVolume *rear_metal_flange_encapsulation_log = new G4LogicalVolume(rear_metal_flange_solid, // G4VSolid fParams.metal_flange_material, // G4Material "rear_metal_flange_encapsulation_log"); - G4Tubs *acrylic_flange_solid = new G4Tubs("acrylic_flange_solid", - 20.8 * CLHEP::cm, // rmin - 25.3 * CLHEP::cm, // rmax - 0.7 * CLHEP::cm, // size z - 0, CLHEP::twopi); // phi G4LogicalVolume *acrylic_flange_encapsulation_log = new G4LogicalVolume(acrylic_flange_solid, // G4VSolid fParams.acrylic_flange_material, // G4Material "acrylic_flange_encapsulation_log"); - G4Box *silica_bag_solid = - new G4Box("silica_bag_solid", 18 * CLHEP::mm, 33 * CLHEP::mm, - 3 * CLHEP::mm); // zhalf + G4LogicalVolume *silica_bag_encapsulation_log = new G4LogicalVolume(silica_bag_solid, // G4VSolid fParams.silica_bag_material, // G4Materil "silica_bag_encapsulation_log"); - G4Tubs *cable_solid = new G4Tubs("cable_solid", - 0 * CLHEP::cm, // rmin - 6.5 * CLHEP::mm, // rmax - 4.5 * CLHEP::cm, // size z - 0, CLHEP::twopi); // phi + G4LogicalVolume *cable_encapsulation_log = new G4LogicalVolume(cable_solid, // G4VSolid fParams.cable_material, // G4Material @@ -422,20 +343,7 @@ EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { G4ThreeVector noTranslation(0., 0., 0.); body_phys = 0; - if (fParams.useEnvelope) { - // place body in envelope - // this will set the pmt that triggers - /* body_phys = new G4PVPlacement( - 0, // no rotation - G4ThreeVector(0.0, 0.0, - 9.8 * CLHEP::cm), // Bounding envelope already constructed to put equator - // at origin - body_log, // the logical volume - prefix + "_body_phys", // a name for this physical volume - envelope_log, // the mother volume - false, // no boolean ops - 0); // copy number*/ - } + // Place inner encapsulation volume within mother, ensure it is first daughter! in_encapsulation_phys = new G4PVPlacement( 0, // no rotation G4ThreeVector(0.0, 0. * CLHEP::cm, @@ -446,6 +354,8 @@ EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { envelope_log, // the mother volume false, // no boolean ops 0); + + // Place PMT within inner encapsulation volume, ensure it is first daughter of first daughter! body_phys = new G4PVPlacement( /// This subtracts the pmt from the in encapsulation volume 0, // no rotation G4ThreeVector(0.0, 0.0, @@ -456,6 +366,8 @@ EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { in_encapsulation_log, // the mother volume false, // no boolean ops 0); // copy number + + // Place rest of the inside components optical_gel_encapsulation_phys = new G4PVPlacement( 0, // no rotation G4ThreeVector(0.0, 0. * CLHEP::cm, @@ -466,7 +378,30 @@ EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { in_encapsulation_log, // the mother volume false, // no boolean ops 0); + + acrylic_flange_encapsulaion_phys = new G4PVPlacement( + 0, // no rotation + G4ThreeVector(1.0, 1.0, + 0.8 * CLHEP::cm), // Bounding envelope already constructed + // to put equator at origin + acrylic_flange_encapsulation_log, // the logical volume + prefix + "_encapsulation_phys", // a name for this physical volume + in_encapsulation_log, // the mother volume + false, // no boolean ops + 0); + + silica_bag_encapsulation_phys = new G4PVPlacement( + 0, // no rotation + G4ThreeVector(0.0, 13.5 * CLHEP::cm, + -7.4 * CLHEP::cm), // Bounding envelope already constructed + // to put equator at origin + silica_bag_encapsulation_log, // the logical volume + prefix + "_encapsulation_phys", // a name for this physical volume + in_encapsulation_log, // the mother volume + false, // no boolean ops + 0); + // PLace outer encapsulation components front_encapsulation_phys = new G4PVPlacement( 0, // no rotation G4ThreeVector(0.0, 0.0, @@ -477,6 +412,7 @@ EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { envelope_log, // the mother volume false, // no boolean ops 0); // copy number + rear_encapsulation_phys = new G4PVPlacement( 0, // no rotation G4ThreeVector(0.0, 0.0, @@ -487,6 +423,7 @@ EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { envelope_log, // the mother volume false, // no boolean ops 0); // copy number + front_metal_encapsulaion_flange_phys = new G4PVPlacement( 0, // no rotation G4ThreeVector(0.0, 0.0, @@ -497,6 +434,7 @@ EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { envelope_log, // the mother volume false, // no boolean ops 0); // copy number + rear_metal_encapsulation_flange_phys = new G4PVPlacement( 0, // no rotation G4ThreeVector(0.0, 0.0, @@ -507,37 +445,7 @@ EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { envelope_log, // the mother volume false, // no boolean ops 0); // copy number - acrylic_flange_encapsulaion_phys = new G4PVPlacement( - 0, // no rotation - G4ThreeVector(1.0, 1.0, - 0.8 * CLHEP::cm), // Bounding envelope already constructed - // to put equator at origin - acrylic_flange_encapsulation_log, // the logical volume - prefix + "_encapsulation_phys", // a name for this physical volume - envelope_log, // the mother volume - false, // no boolean ops - 0); - silica_bag_encapsulation_phys = new G4PVPlacement( - 0, // no rotation - G4ThreeVector(0.0, 13.5 * CLHEP::cm, - -7.4 * CLHEP::cm), // Bounding envelope already constructed - // to put equator at origin - silica_bag_encapsulation_log, // the logical volume - prefix + "_encapsulation_phys", // a name for this physical volume - envelope_log, // the mother volume - false, // no boolean ops - 0); - - /*silica_bag_encapsulation_phys2 = new G4PVPlacement( - 0, // no rotation - G4ThreeVector(0.0, -13.5 * CLHEP::cm, - 7.4 * CLHEP::cm), // Bounding envelope already constructed - // to put equator at origin - silica_bag_encapsulation_log, // the logical volume - prefix + "_encapsulation_phys", // a name for this physical volume - envelope_log, // the mother volume - false, // no boolean ops - 0);*/ + cable_encapsulation_phys = new G4PVPlacement( 0, // no rotation @@ -588,15 +496,6 @@ EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { 0, G4ThreeVector(0.0, 0.0, fParams.dynodeTop - hhDynode), prefix + "_dynode_phys", dynode_log, inner2_phys, false, 0); - /// Encapsulation - // G4RotationMatrix* pmtrot = new G4RotationMatrix(); - // pmtrot->rotateY(angle_y); - // pmtrot->rotateX(angle_x); - // G4ThreeVector offsetfrontencapsulation = G4ThreeVector(0.0, 0.0, - // 0.8*CLHEP::cm); G4ThreeVector offsetfrontencapsulation_rot = - // pmtrot->inverse()(offsetfrontencapsulation); - // G4ThreeVector frontencapsulationpos = pmtpos + offsetacrylicflange_rot + - // offsetfrontencapsulation_rot; // build the optical surface for the dynode straight away since we already // have the logical volume @@ -840,8 +739,7 @@ EncapsulatedPMTConstruction::optical_gel_height_subtraction(const std::string &_ 0., CLHEP::twopi); // cylinder complete in phi return new G4SubtractionSolid(_name, optical_gel_1, gel_subtract, 0, G4ThreeVector(0.0, 0.0, 0.0*CLHEP::cm)); //8.5 - //return inner_encapsulation_solid2; -}// +} G4VSolid * @@ -852,42 +750,13 @@ EncapsulatedPMTConstruction::optical_gel_pmt_subtraction(const std::string &_nam return new G4SubtractionSolid(_name, optical_gel_2, body, 0, G4ThreeVector(0.0, 0.0, 9.8*CLHEP::cm)); //8.5 - //return inner_encapsulation_solid2; -}// +} G4VSolid * EncapsulatedPMTConstruction::NewEnvelopeSolid(const std::string &_name) { - /*G4double zTop = fParams.zEdge[0] + fParams.faceGap; - G4double zBottom = fParams.zEdge[fParams.zEdge.size() - 1]; - G4double rho = fParams.minEnvelopeRadius; - for (unsigned i = 0; i < fParams.rhoEdge.size(); i++) { - if (fParams.rhoEdge[i] > rho) { - rho = fParams.rhoEdge[i]; - } - } - - G4double mainCylHalfHeight = std::max(zTop, -zBottom); - G4double subCylHalfHeight = - (mainCylHalfHeight - std::min(zTop, -zBottom)) / 2.0; - G4double subCylOffset; - if (zTop < -zBottom) { - subCylOffset = zTop + subCylHalfHeight; - } else { - subCylOffset = zBottom - subCylHalfHeight; - } - - G4Tubs *mainEnvelope = new G4Tubs(_name + "_main", 0.0, rho, - mainCylHalfHeight, 0.0, CLHEP::twopi); - G4Tubs *subEnvelope = new G4Tubs(_name + "_sub", 0.0, rho * 1.1, - subCylHalfHeight, 0.0, CLHEP::twopi); - - return new G4SubtractionSolid(_name, mainEnvelope, subEnvelope, 0, - G4ThreeVector(0.0, 0.0, subCylOffset));*/ G4Sphere *outer_s = new G4Sphere(_name+ "_main", 0. * CLHEP::mm, 25.4*CLHEP::cm, 0.0, CLHEP::twopi, 0.0, CLHEP::twopi); - //G4Sphere *inner_s = new G4Sphere(_name+ "_sub", 0. * CLHEP::mm, 25.3*CLHEP::cm, 0.0, CLHEP::twopi, 0.0, CLHEP::twopi); - //return new G4SubtractionSolid(_name, outer_s, inner_s); return outer_s; } diff --git a/src/geo/src/pmt/PMTFactoryBase.cc b/src/geo/src/pmt/PMTFactoryBase.cc index b0976b55..b828fb0c 100644 --- a/src/geo/src/pmt/PMTFactoryBase.cc +++ b/src/geo/src/pmt/PMTFactoryBase.cc @@ -360,9 +360,11 @@ G4VPhysicalVolume *PMTFactoryBase::ConstructPMTs( } // end loop over id - // finally pass the efficiency table to GLG4PMTOpticalModel + // finally pass the efficiency table to GLGS4PMTOpticalModel const G4String modname(volume_name + "_optical_model"); // In case the main pmt volume doesn't correspond to the fastsim region + + // For the encapsulated version, the pmt_body is the daughter of the first daughter G4LogicalVolume *fastsim_log_pmt = log_pmt; G4LogicalVolume *fastsim_log_pmt_dau = 0; if (fastsim_log_pmt->GetFastSimulationManager() == NULL) { From f81167795f23f67a7bb808bf033ddd42d6319b00 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Tue, 15 Apr 2025 15:24:17 +0100 Subject: [PATCH 08/52] Tidy up for pull request --- ratdb/MATERIALS.ratdb | 11 ++++++++ ratdb/OPTICS.ratdb | 63 +++++++++++++++---------------------------- ratdb/PMT.ratdb | 40 +++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 42 deletions(-) diff --git a/ratdb/MATERIALS.ratdb b/ratdb/MATERIALS.ratdb index c23f77e8..048ecb36 100644 --- a/ratdb/MATERIALS.ratdb +++ b/ratdb/MATERIALS.ratdb @@ -787,6 +787,17 @@ nmaterials: 0, elements: ["Hydrogen", "Carbon", "Oxygen"], elemprop: [0.0703, 0.558, 0.3717], } +{ +name: "MATERIAL", +index: "nakano_acrylic", +valid_begin : [0, 0], +valid_end : [0, 0], +density: 1.14, +nelements: 3, +nmaterials: 0, +elements: ["Hydrogen", "Carbon", "Oxygen"], +elemprop: [0.0703, 0.558, 0.3717], +} { name: "MATERIAL", diff --git a/ratdb/OPTICS.ratdb b/ratdb/OPTICS.ratdb index 9bf5aad5..2491c8d0 100644 --- a/ratdb/OPTICS.ratdb +++ b/ratdb/OPTICS.ratdb @@ -391,48 +391,6 @@ ABSLENGTH_value2: [0.1e-3, 0.1e-3, 0.1e-3, 1.0e3, 2.0e3, 1.0e3, 0.5e3, 0.1e-3, ] PROPERTY_LIST: ["RINDEX", "ABSLENGTH", ] } -{ -name: "OPTICS", -index: "borosilicate_glass", -valid_begin : [0, 0], -valid_end : [0, 0], -surface: 1, -finish: "ground", -model: "glisur", -type: "dielectric_dielectric", -polish: 0.9, -RINDEX_option: "wavelength", -// Refractive index of Schott BK7 from https://refractiveindex.info/?shelf=popular_glass&book=BK7&page=SCHOTT -// There is no data below 300 nm, so the Sellmeier formulas extrapolated below using an exponential fit. -RINDEX_value1: [60.0, 100.0, 200.0, 300.0, 400.0, 500.0, 600.0, 700.0, 800.0, ], -RINDEX_value2: [1.707, 1.662, 1.589, 1.551, 1.531, 1.521, 1.516, 1.513, 1.512, ], -ABSLENGTH_option: "wavelength", -ABSLENGTH_value1: [60.0, 200.0, 300.0, 330.0, 500.0, 600.0, 770.0, 800.0, ], -ABSLENGTH_value2: [0.1e-3, 0.1e-3, 0.1e-3, 1.0e3, 2.0e3, 1.0e3, 0.5e3, 0.1e-3, ], -PROPERTY_LIST: ["RINDEX", "ABSLENGTH", ] -} - -{ -name: "OPTICS", -index: "hamamatsu_borosilicate_glass", -valid_begin : [0, 0], -valid_end : [0, 0], -surface: 1, -finish: "ground", -model: "glisur", -type: "dielectric_dielectric", -polish: 0.9, -// Refractive index of Schott BK7 from https://refractiveindex.info/?shelf=popular_glass&book=BK7&page=SCHOTT -// There is no data below 300 nm, so the Sellmeier formulas extrapolated below using an exponential fit. -RINDEX_option: "wavelength", -RINDEX_value1: [60.0, 100.0, 200.0, 300.0, 400.0, 500.0, 600.0, 700.0, 800.0, ], -RINDEX_value2: [1.707, 1.662, 1.589, 1.551, 1.531, 1.521, 1.516, 1.513, 1.512, ], -ABSLENGTH_option: "wavelength", -ABSLENGTH_value1: [60.0, 200.0, 300.0, 330.0, 500.0, 600.0, 770.0, 800.0, ], -ABSLENGTH_value2: [0.1e-3, 0.1e-3, 0.1e-3, 1.0e3, 2.0e3, 1.0e3, 0.5e3, 0.1e-3, ], -PROPERTY_LIST: ["RINDEX", "ABSLENGTH", ] -} - { name: "OPTICS", index: "mirror", @@ -646,6 +604,27 @@ ABSLENGTH_value2: [1.0e-3, 1.0e-3, 0.49e1, 2.75e1, 10.35e1, 14.99e1, 20.41e1, 28 PROPERTY_LIST: ["RINDEX", "ABSLENGTH", ] } +{ +name : "OPTICS", +index : "nakano_acrylic", +valid_begin: [0, 0], +valid_end: [0, 0], + +RINDEX_option: "wavelength", +RINDEX_value1: [60.0, 200.0, 210.0, 220.0, 230.0, 240.0, 250.0, 260.0, 270.0, 280.0, 290.0, 300.0, 310.0, 320.0, 330.0, 340.0, 350.0, 360.0, 370.0, 380.0, 390.0, 400.0, 410.0, 420.0, 430.0, 440.0, 450.0, 460.0, 470.0, 480.0, 490.0, 500.0, 510.0, 520.0, 530.0, 540.0, 550.0, 560.0, 570.0, 580.0, 590.0, 600.0, 610.0, 620.0, 630.0, 640.0, 650.0, 660.0, 670.0, 680.0, 690.0, 700.0, 710.0, 720.0, 730.0, 740.0, 750.0, 760.0, 770.0, 780.0, 790.0, 800.0, ], +RINDEX_value2: [1.597, 1.597, 1.584, 1.573, 1.564, 1.556, 1.550, 1.544, 1.539, 1.534, 1.531, 1.527, 1.524, 1.521, 1.519, 1.516, 1.514, 1.512, 1.510, 1.509, 1.507, 1.506, 1.505, 1.503, 1.502, 1.501, 1.500, 1.499, 1.499, 1.498, 1.497, 1.496, 1.496, 1.495, 1.494, 1.494, 1.493, 1.493, 1.492, 1.492, 1.491, 1.491, 1.490, 1.490, 1.490, 1.489, 1.489, 1.488, 1.488, 1.488, 1.488, 1.487, 1.487, 1.487, 1.486, 1.486, 1.486, 1.486, 1.485, 1.485, 1.485, 1.485, ], +ABSLENGTH_option : "wavelength", +//ABSLENGTH_value1 : [200.0, 201.0, 202.0, 203.0, 204.0, 205.0, 206.0, 207.0, 208.0, 210.0, 211.0, 212.0, 215.0, 217.0, 218.0, 219.0, 220.0, 221.0, 223.0, 224.0, 226.0, 227.0, 228.0, 229.0, 232.0, 233.0, 235.0, 236.0, 237.0, 238.0, 239.0, 241.0, 242.0, 243.0, 244.0, 245.0, 247.0, 248.0, 249.0, 250.0, 251.0, 252.0, 253.0, 254.0, 255.0, 256.0, 257.0, 258.0, 259.0, 260.0, 261.0, 262.0, 263.0, 264.0, 265.0, 266.0, 267.0, 268.0, 269.0, 270.0, 271.0, 272.0, 273.0, 274.0, 275.0, 276.0, 277.0, 278.0, 279.0, 280.0, 281.0, 282.0, 283.0, 284.0, 285.0, 286.0, 287.0, 288.0, 289.0, 290.0, 291.0, 292.0, 293.0, 294.0, 295.0, 296.0, 297.0, 298.0, 299.0, 300.0, 301.0, 302.0, 303.0, 304.0, 305.0, 306.0, 307.0, 308.0, 309.0, 310.0, 311.0, 312.0, 313.0, 314.0, 315.0, 316.0, 317.0, 318.0, 319.0, 320.0, 321.0, 322.0, 323.0, 324.0, 325.0, 326.0, 327.0, 328.0, 329.0, 330.0, 331.0, 332.0, 333.0, 334.0, 335.0, 336.0, 337.0, 338.0, 339.0, 340.0, 341.0, 342.0, 343.0, 344.0, 345.0, 346.0, 347.0, 348.0, 349.0, 350.0, 351.0, 352.0, 353.0, 354.0, 355.0, 356.0, 357.0, 358.0, 359.0, 360.0, 361.0, 362.0, 363.0, 364.0, 365.0, 366.0, 367.0, 368.0, 369.0, 370.0, 371.0, 372.0, 373.0, 374.0, 375.0, 376.0, 377.0, 378.0, 379.0, 380.0, 381.0, 382.0, 383.0, 384.0, 385.0, 386.0, 387.0, 388.0, 389.0, 390.0, 391.0, 392.0, 393.0, 394.0, 395.0, 396.0, 397.0, 398.0, 399.0, 400.0, 401.0, 402.0, 403.0, 404.0, 405.0, 406.0, 407.0, 408.0, 409.0, 410.0, 411.0, 412.0, 413.0, 414.0, 415.0, 416.0, 417.0, 418.0, 419.0, 420.0, 421.0, 422.0, 423.0, 424.0, 425.0, 426.0, 427.0, 428.0, 429.0, 430.0, 431.0, 432.0, 433.0, 434.0, 435.0, 436.0, 437.0, 438.0, 439.0, 440.0, 441.0, 442.0, 443.0, 444.0, 445.0, 446.0, 447.0, 448.0, 449.0, 450.0, 451.0, 452.0, 453.0, 454.0, 455.0, 456.0, 457.0, 458.0, 459.0, 460.0, 461.0, 462.0, 463.0, 464.0, 465.0, 466.0, 467.0, 468.0, 469.0, 470.0, 471.0, 472.0, 473.0, 474.0, 475.0, 476.0, 477.0, 478.0, 479.0, 480.0, 481.0, 482.0, 483.0, 484.0, 485.0, 486.0, 487.0, 488.0, 489.0, 490.0, 491.0, 492.0, 493.0, 494.0, 495.0, 496.0, 497.0, 498.0, 499.0, 500.0, 501.0, 502.0, 503.0, 504.0, 505.0, 506.0, 507.0, 508.0, 509.0, 510.0, 511.0, 512.0, 513.0, 514.0, 515.0, 516.0, 517.0, 518.0, 519.0, 520.0, 521.0, 522.0, 523.0, 524.0, 525.0, 526.0, 527.0, 528.0, 529.0, 530.0, 531.0, 532.0, 533.0, 534.0, 535.0, 536.0, 537.0, 538.0, 539.0, 540.0, 541.0, 542.0, 543.0, 544.0, 545.0, 546.0, 547.0, 548.0, 549.0, 550.0, 551.0, 552.0, 553.0, 554.0, 555.0, 556.0, 557.0, 558.0, 559.0, 560.0, 561.0, 562.0, 563.0, 564.0, 565.0, 566.0, 567.0, 568.0, 569.0, 570.0, 571.0, 572.0, 573.0, 574.0, 575.0, 576.0, 577.0, 578.0, 579.0, 580.0, 581.0, 582.0, 583.0, 584.0, 585.0, 586.0, 587.0, 588.0, 589.0, 590.0, 591.0, 592.0, 593.0, 594.0, 595.0, 596.0, 597.0, 598.0, 599.0, 600.0, 601.0, 602.0, 603.0, 604.0, 605.0, 606.0, 607.0, 608.0, 609.0, 610.0, 611.0, 612.0, 613.0, 614.0, 615.0, 616.0, 617.0, 618.0, 619.0, 620.0, 621.0, 622.0, 623.0, 624.0, 625.0, 626.0, 627.0, 628.0, 629.0, 630.0, 631.0, 632.0, 633.0, 634.0, 635.0, 636.0, 637.0, 638.0, 639.0, 640.0, 641.0, 642.0, 643.0, 644.0, 645.0, 646.0, 647.0, 648.0, 649.0, 650.0], +//ABSLENGTH_value2 : [6.766646, 6.766646, 6.106986, 6.106986, 5.086679, 5.234611, 5.902842, 4.893309, 5.234611, 5.234611, 5.234611, 5.234611, 4.893309, 5.84476, 5.466055, 5.086679, 5.234611, 4.893309, 5.086679, 5.234611, 5.355951, 5.466055, 5.637248, 5.637248, 4.573503, 4.573503, 4.893309, 4.573503, 5.234611, 5.355951, 5.086679, 5.234611, 5.234611, 5.086679, 5.086679, 5.086679, 4.893309, 5.234611, 5.466055, 5.355951, 4.893309, 5.466055, 5.355951, 5.234611, 5.466055, 5.466055, 5.466055, 5.355951, 5.556357, 5.466055, 5.234611, 5.466055, 5.782536, 5.84476, 5.466055, 5.556357, 5.637248, 5.902842, 5.782536, 5.466055, 5.556357, 5.957376, 5.84476, 5.466055, 5.902842, 5.902842, 5.84476, 5.710734, 5.957376, 5.782536, 5.902842, 6.151102, 6.351271, 6.275325, 6.236473, 6.151102, 6.106986, 6.196074, 6.351271, 6.151102, 6.351271, 6.766646, 7.208724, 8.193268, 9.868894, 11.880833, 14.244282, 16.784146, 19.717709, 23.049586, 26.544354, 30.195035, 34.219501, 38.321886, 42.39765, 46.533259, 50.832953, 54.948511, 58.922905, 63.085969, 67.41336, 71.748641, 76.120996, 80.767293, 85.202911, 89.821651, 94.348418, 98.754483, 103.012398, 107.681056, 112.008174, 115.824833, 119.440937, 123.252061, 127.16593, 132.325345, 138.370286, 144.227796, 150.049118, 156.658243, 163.287528, 170.370174, 176.796012, 182.930312, 188.820709, 194.353756, 199.864259, 205.589488, 209.876284, 216.19017, 222.810381, 227.815651, 232.801149, 238.132189, 243.486785, 249.15384, 255.109166, 260.232763, 264.958051, 271.619689, 277.810437, 283.393802, 289.664446, 295.411718, 300.792124, 307.391599, 314.538422, 320.976971, 326.690368, 332.629732, 339.013314, 345.045319, 351.023973, 357.949102, 364.397882, 370.92331, 376.497665, 384.094671, 389.787601, 397.409983, 403.865868, 410.067323, 416.681403, 422.050509, 429.345314, 434.771993, 440.719417, 445.811451, 451.43275, 457.327331, 460.508839, 464.304619, 470.003848, 473.055345, 476.825729, 480.345269, 482.357526, 485.480714, 489.044336, 490.963178, 493.948192, 496.811707, 498.870234, 500.366134, 502.035214, 502.370299, 502.452762, 502.959098, 503.041744, 504.472855, 505.661163, 506.597773, 506.765371, 508.390937, 508.908706, 509.421833, 511.501276, 513.327622, 513.499477, 515.258672, 516.489989, 517.290734, 517.465122, 519.425929, 521.035411, 521.849624, 523.568564, 524.110178, 525.112888, 526.942644, 527.406503, 528.784576, 529.622008, 531.200547, 532.321296, 534.483581, 534.675357, 535.716939, 535.716939, 537.711638, 539.242129, 539.726836, 540.395456, 540.977048, 541.654968, 541.458395, 541.750133, 542.722638, 544.082073, 545.358034, 546.433226, 547.124249, 547.616082, 549.103165, 549.402809, 549.702766, 550.401701, 551.397501, 552.600961, 553.710197, 553.306948, 553.306948, 554.319438, 554.624538, 555.841487, 556.348386, 556.856167, 556.856167, 558.492409, 559.421894, 558.391556, 560.557435, 560.34757, 561.072579, 562.214531, 562.418919, 562.214531, 563.983763, 564.614778, 565.033912, 565.556944, 567.034673, 567.665291, 569.258173, 568.192988, 567.561251, 567.984574, 569.153575, 568.937521, 569.258173, 568.833034, 568.624172, 568.408502, 568.088763, 566.6127, 565.977416, 565.770552, 564.086554, 563.046592, 561.901413, 561.384816, 560.34757, 560.246076, 560.036433, 558.391556, 558.70095, 558.189954, 558.492409, 559.523103, 561.276174, 562.105583, 562.944163, 565.033912, 565.660284, 566.398485, 566.923934, 567.665291, 568.833034, 570.110275, 570.754456, 570.754456, 573.005963, 573.111919, 572.469695, 573.005963, 574.734174, 576.036885, 577.345253, 576.586709, 576.586709, 576.908499, 578.443502, 577.567452, 577.897468, 579.213936, 579.762353, 579.762353, 580.869419, 581.75508, 581.52979, 582.533976, 582.417379, 582.643326, 583.307562, 583.534171, 582.978913, 583.088423, 582.862145, 584.090441, 584.427625, 584.985526, 583.87074, 583.87074, 584.317633, 583.87074, 582.978913, 584.090441, 584.427625, 584.655067, 583.088423, 583.197973, 586.333085, 586.561948, 585.772723, 585.772723, 586.333085, 587.464299, 586.451186, 586.67275, 586.561948, 587.805219, 587.694008, 588.934436, 589.053543, 588.822816, 589.508059, 588.822816, 589.508059, 589.963247, 591.332857, 591.678088, 590.531309, 590.075282, 590.075282, 591.100419, 591.332857, 590.306949, 590.763319, 590.187357, 589.843789, 590.075282, 590.763319, 589.843789, 590.306949, 589.843789, 589.619928, 587.464299, 586.901867, 586.111767, 584.537656, 583.534171, 581.52979, 579.654034, 577.567452, 575.495184, 572.794163, 570.432192, 567.880422, 566.191327, 564.504939, 564.717789, 564.923918, 563.668761, 563.983763, 564.402003, 566.820153, 567.984574, 569.579171, 571.182345, 572.900044, 573.005963, 573.543192, 573.868825, 574.407602, 574.954456, 575.388384, 575.167785, 576.036885, 576.258122, 576.801198, 577.459916, 578.774476, 577.345253, 578.774476, 577.459916, 577.897468, 576.908499, 576.365231, 577.130377, 578.227844, 578.11289, 577.789814, 575.495184, 576.151052, 577.567452, 577.130377, 575.495184, 573.22498, 572.251229, 570.642325, 572.039962, 570.327181, 569.362809, 567.242421, 566.191327, 565.977416, 565.033912, 563.778289, 560.970834, 559.421894], +//ABSLENGTH_value1: [60.0, 199.0, 200.0, 300.0, 310.0, 320.0, 330.0, 340.0, 350.0, 360.0, 380.0, 400.0, 450.0, 800.0], +//ABSLENGTH_value2: [1.0e-3, 1.0e-3, 0.49e1, 2.04e1, 5.56e1, 14.28e1, 25.00e1, 50.00e1, 100.00e1, 100.00e1, 200.00e1, 200.00e1, 200.00e1, 200.00e1], +//ABSLENGTH_value2: [1.0e6, 1.0e6, 1.0e6, 1.0e6, 1.0e6, 1.0e6, 1.0e6, 1.0e6, 1.0e6, 1.0e6, 1.0e6, 1.0e6, 1.0e6, 1.0e6], +//New ABSLENGTH to match experimental +ABSLENGTH_value1: [60.0, 200, 300.0, 375.0, 400.0, 410.0, 420.0, 430.0, 440.0, 450.0, 460.0, 480.0, 500.0, 550.0, 800.0], +ABSLENGTH_value2: [1.0e-6, 1.0e-6, 1.0e-6, 5.56e1, 5.56e1, 8.56e1, 8.56e1, 8.56e1, 8.56e1, 8.56e1, 8.56e1, 8.56e1, 8.56e1, 8.56e1, 8.56e1], + +PROPERTY_LIST: ["RINDEX","ABSLENGTH"] +} { diff --git a/ratdb/PMT.ratdb b/ratdb/PMT.ratdb index ab75f8c5..9256ca2c 100644 --- a/ratdb/PMT.ratdb +++ b/ratdb/PMT.ratdb @@ -451,6 +451,46 @@ z_origin: [ -40.0, 0.0, 0.0, 40.0, -142.0 ], noise_rate: 10000.0, // Hz } +{ +//An encapsulated version of the pmt +name: "PMT", +index: "r7081pe_encapsulated", +valid_begin: [0,0], +valid_end: [0,0], + +construction: "encapsulated", + +dynode_material: "stainless_steel", +glass_material: "glass", +pmt_vacuum_material: "pmt_vacuum", +photocathode_surface: "photocathode_R7081", +photocathode_MINrho: 110.0, +photocathode_MAXrho: 126.5, +mirror_surface: "mirror", +dynode_surface: "stainless_steel", + +inner_encapsulation_material: "glass" +front_encapsulation_material: "nakano_acrylic" +rear_encapsulation_material: "acrylic_black" +metal_flange_material: "stainless_steel" +acrylic_flange_material: "nakano_acrylic" +silica_bag_material: "acrylic_white" +cable_material: "acrylic_black" + + +dynode_radius: 27.5, // mm +dynode_top: -5.9, // mm +wall_thickness: 3.0, // mm + +z_edge: [ 96.7, 40.0, 0.0, -40.0, -90.0, -142.0 ], +rho_edge: [ 0.0, 111.0, 126.5, 111.0, 42.25, 42.25 ], +z_origin: [ -40.0, 0.0, 0.0, 40.0, -142.0 ], + +noise_rate: 10000.0, // Hz +} + + + { name: "PMT", index: "r3600", From 01a62cf14369bf8ad09578e4a2cb1c1dee5256f3 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Tue, 15 Apr 2025 17:54:38 +0100 Subject: [PATCH 09/52] Added encapsulation --- ratdb/OPTICS.ratdb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ratdb/OPTICS.ratdb b/ratdb/OPTICS.ratdb index 2491c8d0..577cf439 100644 --- a/ratdb/OPTICS.ratdb +++ b/ratdb/OPTICS.ratdb @@ -614,11 +614,6 @@ RINDEX_option: "wavelength", RINDEX_value1: [60.0, 200.0, 210.0, 220.0, 230.0, 240.0, 250.0, 260.0, 270.0, 280.0, 290.0, 300.0, 310.0, 320.0, 330.0, 340.0, 350.0, 360.0, 370.0, 380.0, 390.0, 400.0, 410.0, 420.0, 430.0, 440.0, 450.0, 460.0, 470.0, 480.0, 490.0, 500.0, 510.0, 520.0, 530.0, 540.0, 550.0, 560.0, 570.0, 580.0, 590.0, 600.0, 610.0, 620.0, 630.0, 640.0, 650.0, 660.0, 670.0, 680.0, 690.0, 700.0, 710.0, 720.0, 730.0, 740.0, 750.0, 760.0, 770.0, 780.0, 790.0, 800.0, ], RINDEX_value2: [1.597, 1.597, 1.584, 1.573, 1.564, 1.556, 1.550, 1.544, 1.539, 1.534, 1.531, 1.527, 1.524, 1.521, 1.519, 1.516, 1.514, 1.512, 1.510, 1.509, 1.507, 1.506, 1.505, 1.503, 1.502, 1.501, 1.500, 1.499, 1.499, 1.498, 1.497, 1.496, 1.496, 1.495, 1.494, 1.494, 1.493, 1.493, 1.492, 1.492, 1.491, 1.491, 1.490, 1.490, 1.490, 1.489, 1.489, 1.488, 1.488, 1.488, 1.488, 1.487, 1.487, 1.487, 1.486, 1.486, 1.486, 1.486, 1.485, 1.485, 1.485, 1.485, ], ABSLENGTH_option : "wavelength", -//ABSLENGTH_value1 : [200.0, 201.0, 202.0, 203.0, 204.0, 205.0, 206.0, 207.0, 208.0, 210.0, 211.0, 212.0, 215.0, 217.0, 218.0, 219.0, 220.0, 221.0, 223.0, 224.0, 226.0, 227.0, 228.0, 229.0, 232.0, 233.0, 235.0, 236.0, 237.0, 238.0, 239.0, 241.0, 242.0, 243.0, 244.0, 245.0, 247.0, 248.0, 249.0, 250.0, 251.0, 252.0, 253.0, 254.0, 255.0, 256.0, 257.0, 258.0, 259.0, 260.0, 261.0, 262.0, 263.0, 264.0, 265.0, 266.0, 267.0, 268.0, 269.0, 270.0, 271.0, 272.0, 273.0, 274.0, 275.0, 276.0, 277.0, 278.0, 279.0, 280.0, 281.0, 282.0, 283.0, 284.0, 285.0, 286.0, 287.0, 288.0, 289.0, 290.0, 291.0, 292.0, 293.0, 294.0, 295.0, 296.0, 297.0, 298.0, 299.0, 300.0, 301.0, 302.0, 303.0, 304.0, 305.0, 306.0, 307.0, 308.0, 309.0, 310.0, 311.0, 312.0, 313.0, 314.0, 315.0, 316.0, 317.0, 318.0, 319.0, 320.0, 321.0, 322.0, 323.0, 324.0, 325.0, 326.0, 327.0, 328.0, 329.0, 330.0, 331.0, 332.0, 333.0, 334.0, 335.0, 336.0, 337.0, 338.0, 339.0, 340.0, 341.0, 342.0, 343.0, 344.0, 345.0, 346.0, 347.0, 348.0, 349.0, 350.0, 351.0, 352.0, 353.0, 354.0, 355.0, 356.0, 357.0, 358.0, 359.0, 360.0, 361.0, 362.0, 363.0, 364.0, 365.0, 366.0, 367.0, 368.0, 369.0, 370.0, 371.0, 372.0, 373.0, 374.0, 375.0, 376.0, 377.0, 378.0, 379.0, 380.0, 381.0, 382.0, 383.0, 384.0, 385.0, 386.0, 387.0, 388.0, 389.0, 390.0, 391.0, 392.0, 393.0, 394.0, 395.0, 396.0, 397.0, 398.0, 399.0, 400.0, 401.0, 402.0, 403.0, 404.0, 405.0, 406.0, 407.0, 408.0, 409.0, 410.0, 411.0, 412.0, 413.0, 414.0, 415.0, 416.0, 417.0, 418.0, 419.0, 420.0, 421.0, 422.0, 423.0, 424.0, 425.0, 426.0, 427.0, 428.0, 429.0, 430.0, 431.0, 432.0, 433.0, 434.0, 435.0, 436.0, 437.0, 438.0, 439.0, 440.0, 441.0, 442.0, 443.0, 444.0, 445.0, 446.0, 447.0, 448.0, 449.0, 450.0, 451.0, 452.0, 453.0, 454.0, 455.0, 456.0, 457.0, 458.0, 459.0, 460.0, 461.0, 462.0, 463.0, 464.0, 465.0, 466.0, 467.0, 468.0, 469.0, 470.0, 471.0, 472.0, 473.0, 474.0, 475.0, 476.0, 477.0, 478.0, 479.0, 480.0, 481.0, 482.0, 483.0, 484.0, 485.0, 486.0, 487.0, 488.0, 489.0, 490.0, 491.0, 492.0, 493.0, 494.0, 495.0, 496.0, 497.0, 498.0, 499.0, 500.0, 501.0, 502.0, 503.0, 504.0, 505.0, 506.0, 507.0, 508.0, 509.0, 510.0, 511.0, 512.0, 513.0, 514.0, 515.0, 516.0, 517.0, 518.0, 519.0, 520.0, 521.0, 522.0, 523.0, 524.0, 525.0, 526.0, 527.0, 528.0, 529.0, 530.0, 531.0, 532.0, 533.0, 534.0, 535.0, 536.0, 537.0, 538.0, 539.0, 540.0, 541.0, 542.0, 543.0, 544.0, 545.0, 546.0, 547.0, 548.0, 549.0, 550.0, 551.0, 552.0, 553.0, 554.0, 555.0, 556.0, 557.0, 558.0, 559.0, 560.0, 561.0, 562.0, 563.0, 564.0, 565.0, 566.0, 567.0, 568.0, 569.0, 570.0, 571.0, 572.0, 573.0, 574.0, 575.0, 576.0, 577.0, 578.0, 579.0, 580.0, 581.0, 582.0, 583.0, 584.0, 585.0, 586.0, 587.0, 588.0, 589.0, 590.0, 591.0, 592.0, 593.0, 594.0, 595.0, 596.0, 597.0, 598.0, 599.0, 600.0, 601.0, 602.0, 603.0, 604.0, 605.0, 606.0, 607.0, 608.0, 609.0, 610.0, 611.0, 612.0, 613.0, 614.0, 615.0, 616.0, 617.0, 618.0, 619.0, 620.0, 621.0, 622.0, 623.0, 624.0, 625.0, 626.0, 627.0, 628.0, 629.0, 630.0, 631.0, 632.0, 633.0, 634.0, 635.0, 636.0, 637.0, 638.0, 639.0, 640.0, 641.0, 642.0, 643.0, 644.0, 645.0, 646.0, 647.0, 648.0, 649.0, 650.0], -//ABSLENGTH_value2 : [6.766646, 6.766646, 6.106986, 6.106986, 5.086679, 5.234611, 5.902842, 4.893309, 5.234611, 5.234611, 5.234611, 5.234611, 4.893309, 5.84476, 5.466055, 5.086679, 5.234611, 4.893309, 5.086679, 5.234611, 5.355951, 5.466055, 5.637248, 5.637248, 4.573503, 4.573503, 4.893309, 4.573503, 5.234611, 5.355951, 5.086679, 5.234611, 5.234611, 5.086679, 5.086679, 5.086679, 4.893309, 5.234611, 5.466055, 5.355951, 4.893309, 5.466055, 5.355951, 5.234611, 5.466055, 5.466055, 5.466055, 5.355951, 5.556357, 5.466055, 5.234611, 5.466055, 5.782536, 5.84476, 5.466055, 5.556357, 5.637248, 5.902842, 5.782536, 5.466055, 5.556357, 5.957376, 5.84476, 5.466055, 5.902842, 5.902842, 5.84476, 5.710734, 5.957376, 5.782536, 5.902842, 6.151102, 6.351271, 6.275325, 6.236473, 6.151102, 6.106986, 6.196074, 6.351271, 6.151102, 6.351271, 6.766646, 7.208724, 8.193268, 9.868894, 11.880833, 14.244282, 16.784146, 19.717709, 23.049586, 26.544354, 30.195035, 34.219501, 38.321886, 42.39765, 46.533259, 50.832953, 54.948511, 58.922905, 63.085969, 67.41336, 71.748641, 76.120996, 80.767293, 85.202911, 89.821651, 94.348418, 98.754483, 103.012398, 107.681056, 112.008174, 115.824833, 119.440937, 123.252061, 127.16593, 132.325345, 138.370286, 144.227796, 150.049118, 156.658243, 163.287528, 170.370174, 176.796012, 182.930312, 188.820709, 194.353756, 199.864259, 205.589488, 209.876284, 216.19017, 222.810381, 227.815651, 232.801149, 238.132189, 243.486785, 249.15384, 255.109166, 260.232763, 264.958051, 271.619689, 277.810437, 283.393802, 289.664446, 295.411718, 300.792124, 307.391599, 314.538422, 320.976971, 326.690368, 332.629732, 339.013314, 345.045319, 351.023973, 357.949102, 364.397882, 370.92331, 376.497665, 384.094671, 389.787601, 397.409983, 403.865868, 410.067323, 416.681403, 422.050509, 429.345314, 434.771993, 440.719417, 445.811451, 451.43275, 457.327331, 460.508839, 464.304619, 470.003848, 473.055345, 476.825729, 480.345269, 482.357526, 485.480714, 489.044336, 490.963178, 493.948192, 496.811707, 498.870234, 500.366134, 502.035214, 502.370299, 502.452762, 502.959098, 503.041744, 504.472855, 505.661163, 506.597773, 506.765371, 508.390937, 508.908706, 509.421833, 511.501276, 513.327622, 513.499477, 515.258672, 516.489989, 517.290734, 517.465122, 519.425929, 521.035411, 521.849624, 523.568564, 524.110178, 525.112888, 526.942644, 527.406503, 528.784576, 529.622008, 531.200547, 532.321296, 534.483581, 534.675357, 535.716939, 535.716939, 537.711638, 539.242129, 539.726836, 540.395456, 540.977048, 541.654968, 541.458395, 541.750133, 542.722638, 544.082073, 545.358034, 546.433226, 547.124249, 547.616082, 549.103165, 549.402809, 549.702766, 550.401701, 551.397501, 552.600961, 553.710197, 553.306948, 553.306948, 554.319438, 554.624538, 555.841487, 556.348386, 556.856167, 556.856167, 558.492409, 559.421894, 558.391556, 560.557435, 560.34757, 561.072579, 562.214531, 562.418919, 562.214531, 563.983763, 564.614778, 565.033912, 565.556944, 567.034673, 567.665291, 569.258173, 568.192988, 567.561251, 567.984574, 569.153575, 568.937521, 569.258173, 568.833034, 568.624172, 568.408502, 568.088763, 566.6127, 565.977416, 565.770552, 564.086554, 563.046592, 561.901413, 561.384816, 560.34757, 560.246076, 560.036433, 558.391556, 558.70095, 558.189954, 558.492409, 559.523103, 561.276174, 562.105583, 562.944163, 565.033912, 565.660284, 566.398485, 566.923934, 567.665291, 568.833034, 570.110275, 570.754456, 570.754456, 573.005963, 573.111919, 572.469695, 573.005963, 574.734174, 576.036885, 577.345253, 576.586709, 576.586709, 576.908499, 578.443502, 577.567452, 577.897468, 579.213936, 579.762353, 579.762353, 580.869419, 581.75508, 581.52979, 582.533976, 582.417379, 582.643326, 583.307562, 583.534171, 582.978913, 583.088423, 582.862145, 584.090441, 584.427625, 584.985526, 583.87074, 583.87074, 584.317633, 583.87074, 582.978913, 584.090441, 584.427625, 584.655067, 583.088423, 583.197973, 586.333085, 586.561948, 585.772723, 585.772723, 586.333085, 587.464299, 586.451186, 586.67275, 586.561948, 587.805219, 587.694008, 588.934436, 589.053543, 588.822816, 589.508059, 588.822816, 589.508059, 589.963247, 591.332857, 591.678088, 590.531309, 590.075282, 590.075282, 591.100419, 591.332857, 590.306949, 590.763319, 590.187357, 589.843789, 590.075282, 590.763319, 589.843789, 590.306949, 589.843789, 589.619928, 587.464299, 586.901867, 586.111767, 584.537656, 583.534171, 581.52979, 579.654034, 577.567452, 575.495184, 572.794163, 570.432192, 567.880422, 566.191327, 564.504939, 564.717789, 564.923918, 563.668761, 563.983763, 564.402003, 566.820153, 567.984574, 569.579171, 571.182345, 572.900044, 573.005963, 573.543192, 573.868825, 574.407602, 574.954456, 575.388384, 575.167785, 576.036885, 576.258122, 576.801198, 577.459916, 578.774476, 577.345253, 578.774476, 577.459916, 577.897468, 576.908499, 576.365231, 577.130377, 578.227844, 578.11289, 577.789814, 575.495184, 576.151052, 577.567452, 577.130377, 575.495184, 573.22498, 572.251229, 570.642325, 572.039962, 570.327181, 569.362809, 567.242421, 566.191327, 565.977416, 565.033912, 563.778289, 560.970834, 559.421894], -//ABSLENGTH_value1: [60.0, 199.0, 200.0, 300.0, 310.0, 320.0, 330.0, 340.0, 350.0, 360.0, 380.0, 400.0, 450.0, 800.0], -//ABSLENGTH_value2: [1.0e-3, 1.0e-3, 0.49e1, 2.04e1, 5.56e1, 14.28e1, 25.00e1, 50.00e1, 100.00e1, 100.00e1, 200.00e1, 200.00e1, 200.00e1, 200.00e1], -//ABSLENGTH_value2: [1.0e6, 1.0e6, 1.0e6, 1.0e6, 1.0e6, 1.0e6, 1.0e6, 1.0e6, 1.0e6, 1.0e6, 1.0e6, 1.0e6, 1.0e6, 1.0e6], //New ABSLENGTH to match experimental ABSLENGTH_value1: [60.0, 200, 300.0, 375.0, 400.0, 410.0, 420.0, 430.0, 440.0, 450.0, 460.0, 480.0, 500.0, 550.0, 800.0], ABSLENGTH_value2: [1.0e-6, 1.0e-6, 1.0e-6, 5.56e1, 5.56e1, 8.56e1, 8.56e1, 8.56e1, 8.56e1, 8.56e1, 8.56e1, 8.56e1, 8.56e1, 8.56e1, 8.56e1], From 065e51aab95b99697396844c580464999a90a80f Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Tue, 15 Apr 2025 18:07:57 +0100 Subject: [PATCH 10/52] Added encapsulation --- ratdb/OPTICS.ratdb | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/ratdb/OPTICS.ratdb b/ratdb/OPTICS.ratdb index 6b0d05c6..577cf439 100644 --- a/ratdb/OPTICS.ratdb +++ b/ratdb/OPTICS.ratdb @@ -345,7 +345,8 @@ RINDEX_value1: [60.0, 200.0, 300.0, 600.0, 800.0, ], RINDEX_value2: [1.76, 1.76, 1.76, 1.76, 1.76, ], //index of refraction looked up online ABSLENGTH_option: "wavelength", ABSLENGTH_value1: [60.0, 180.0, 200.0, 250.0, 400.0, 1000.0, 2000.0, 3000.0, 4000.0, 5000.0, 7000.0, ], //values calculate from infromation from ceramtech documentation -ABSLENGTH_value2: [0.1e-3, 0.1e-3, 10.0, 44.81, 52.67, 61.53, 61.53, 61.53, 50.39, 28.03, 0.1e-3, ], +ABSLENGTH_value2: [0.1e-3, 0.1e-3, 10.0, 44.81, 52.67, 61.53, 61.53, 61.53, 50.39, +28.03,0.1e-3, ], PROPERTY_LIST: ["RINDEX", "ABSLENGTH", ] } @@ -354,7 +355,7 @@ PROPERTY_LIST: ["RINDEX", "ABSLENGTH", ] { name: "OPTICS", -index: "quartz", // fused quartz +index: "quartz", valid_begin : [0, 0], valid_end : [0, 0], surface: 1, @@ -363,13 +364,11 @@ model: "glisur", type: "dielectric_dielectric", polish: 0.9, RINDEX_option: "wavelength", -// Refractive index of Fused silica (fused quartz) from https://refractiveindex.info/?shelf=glass&book=fused_silica&page=Malitson -RINDEX_value1: [60.0, 117.0, 120.0, 140.0, 160.0, 180.0, 200.0, 220.0, 240.0, 260.0, 280.0, 300.0, 320.0, 340.0, 360.0, 380.0, 400.0, 420.0, 440.0, 460.0, 480.0, 500.0, 520.0, 540.0, 560.0, 580.0, 600.0, 620.0, 640.0, 660.0, 680.0, 700.0, 720.0, 740.0, 760.0, 780.0, 800.0, 820.0, 840.0, 860.0, 880.0, 900.0, 920.0, 940.0, 960.0, 980.0, 1000, ], -RINDEX_value2: [5.7982, 5.7982, 2.9406, 1.7966, 1.6479, 1.5853, 1.5505, 1.5285, 1.5133, 1.5024, 1.4942, 1.4878, 1.4827, 1.4787, 1.4753, 1.4725, 1.4701, 1.4681, 1.4663, 1.4648, 1.4635, 1.4623, 1.4613, 1.4603, 1.4595, 1.4587, 1.4580, 1.4574, 1.4568, 1.4563, 1.4558, 1.4553, 1.4549, 1.4544, 1.4540, 1.4537, 1.4533, 1.4530, 1.4527, 1.4523, 1.4520, 1.4518, 1.4515, 1.4512, 1.4509, 1.4507, 1.4504, ], +RINDEX_value1: [60.0, 200.0, 300.0, 600.0, 800.0, ], +RINDEX_value2: [1.458, 1.458, 1.458, 1.458, 1.458, ], ABSLENGTH_option: "wavelength", -// Values inherited from "glass" except cutoff set to ~160 nm based on https://www.hamamatsu.com/us/en/support/glossary/w.html -ABSLENGTH_value1: [60.0, 130.0, 160.0, 330.0, 500.0, 600.0, 770.0, 800.0, ], -ABSLENGTH_value2: [0.1e-3, 0.1e-3, 1.0e3, 1.0e3, 2.0e3, 1.0e3, 0.5e3, 0.1e-3, ], +ABSLENGTH_value1: [60.0, 200.0, 300.0, 330.0, 500.0, 600.0, 770.0, 800.0, ], +ABSLENGTH_value2: [0.1e-3, 0.1e-3, 0.1e-3, 1.0e3, 2.0e3, 1.0e3, 0.5e3, 0.1e-3, ], PROPERTY_LIST: ["RINDEX", "ABSLENGTH", ] } From 553b89682be7a6783e4ede02725b14c705f8d702 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Tue, 15 Apr 2025 18:09:55 +0100 Subject: [PATCH 11/52] Added encapsulation --- ratdb/PMT.ratdb | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/ratdb/PMT.ratdb b/ratdb/PMT.ratdb index f5fe03af..9256ca2c 100644 --- a/ratdb/PMT.ratdb +++ b/ratdb/PMT.ratdb @@ -7,7 +7,7 @@ valid_end: [0,0], construction: "toroidal", dynode_material: "stainless_steel", -glass_material: "hamamatsu_borosilicate_glass", +glass_material: "glass", pmt_vacuum_material: "pmt_vacuum", // dilute air photocathode_surface: "photocathode", mirror_surface: "mirror", @@ -33,7 +33,7 @@ valid_end: [0,0], construction: "toroidal", dynode_material: "stainless_steel", -glass_material: "hamamatsu_borosilicate_glass", +glass_material: "glass", pmt_vacuum_material: "pmt_vacuum", // dilute air photocathode_surface: "photocathode_r14688", mirror_surface: "mirror", @@ -59,7 +59,7 @@ valid_end: [0,0], construction: "toroidal", dynode_material: "stainless_steel", -glass_material: "hamamatsu_borosilicate_glass", +glass_material: "glass", pmt_vacuum_material: "pmt_vacuum", // dilute air photocathode_surface: "photocathode_R1408", mirror_surface: "mirror", @@ -86,7 +86,7 @@ valid_end: [0,0], construction: "revolution", dynode_material: "stainless_steel", -glass_material: "hamamatsu_borosilicate_glass", +glass_material: "glass", pmt_vacuum_material: "pmt_vacuum", photocathode_surface: "photocathode_R1408", mirror_surface: "mirror", @@ -147,7 +147,7 @@ valid_end: [0,0], construction: "toroidal", dynode_material: "stainless_steel", -glass_material: "hamamatsu_borosilicate_glass", +glass_material: "glass", pmt_vacuum_material: "pmt_vacuum", photocathode_surface: "photocathode_R11780", mirror_surface: "mirror", @@ -174,7 +174,7 @@ valid_end: [0,0], construction: "revolution", dynode_material: "stainless_steel", -glass_material: "hamamatsu_borosilicate_glass", +glass_material: "glass", pmt_vacuum_material: "pmt_vacuum", photocathode_surface: "photocathode_R11780", mirror_surface: "mirror", @@ -237,7 +237,7 @@ valid_end: [0,0], construction: "toroidal", dynode_material: "stainless_steel", -glass_material: "hamamatsu_borosilicate_glass", +glass_material: "glass", pmt_vacuum_material: "pmt_vacuum", photocathode_surface: "photocathode_R7081HQE", mirror_surface: "mirror", @@ -263,7 +263,7 @@ valid_end: [0,0], construction: "toroidal", dynode_material: "stainless_steel", -glass_material: "hamamatsu_borosilicate_glass", +glass_material: "glass", pmt_vacuum_material: "pmt_vacuum", photocathode_surface: "photocathode_R7081", mirror_surface: "mirror", @@ -290,7 +290,7 @@ valid_end: [0,0], construction: "revolution", dynode_material: "stainless_steel", -glass_material: "hamamatsu_borosilicate_glass", +glass_material: "glass", pmt_vacuum_material: "pmt_vacuum", photocathode_surface: "photocathode_R7081", mirror_surface: "mirror", @@ -326,7 +326,7 @@ valid_end: [0,0], construction: "revolution", dynode_material: "stainless_steel", -glass_material: "hamamatsu_borosilicate_glass", +glass_material: "glass", pmt_vacuum_material: "pmt_vacuum", photocathode_surface: "photocathode_R1408", //used the 1408 photocathode in SNO+ rat mirror_surface: "mirror", @@ -362,7 +362,7 @@ valid_end: [0,0], construction: "toroidal", dynode_material: "stainless_steel", -glass_material: "borosilicate_glass", +glass_material: "glass", pmt_vacuum_material: "pmt_vacuum", // dilute air photocathode_surface: "photocathode_et9390b", mirror_surface: "mirror", @@ -388,7 +388,7 @@ valid_end: [0,0], construction: "cubic", case_material: "acrylic_white", -glass_material: "hamamatsu_borosilicate_glass", +glass_material: "glass", pmt_vacuum_material: "pmt_vacuum", photocathode_surface: "photocathode_H11934", mirror_surface: "mirror", @@ -432,7 +432,7 @@ valid_end: [0,0], construction: "toroidal", dynode_material: "stainless_steel", -glass_material: "hamamatsu_borosilicate_glass", +glass_material: "glass", pmt_vacuum_material: "pmt_vacuum", photocathode_surface: "photocathode_R7081", photocathode_MINrho: 110.0, @@ -499,7 +499,7 @@ valid_end: [0,0], construction: "toroidal", dynode_material: "stainless_steel", -glass_material: "hamamatsu_borosilicate_glass", +glass_material: "glass", pmt_vacuum_material: "pmt_vacuum", photocathode_surface: "photocathode_R3600", photocathode_MINrho: 230.0, From ac0c996003d90a7cc324673b0bdc36b786d86077 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Tue, 15 Apr 2025 18:11:37 +0100 Subject: [PATCH 12/52] Added encapsulation --- src/geo/src/pmt/EncapsulatedPMTConstruction.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/geo/src/pmt/EncapsulatedPMTConstruction.cc b/src/geo/src/pmt/EncapsulatedPMTConstruction.cc index 4bb6e4c6..80f7946e 100644 --- a/src/geo/src/pmt/EncapsulatedPMTConstruction.cc +++ b/src/geo/src/pmt/EncapsulatedPMTConstruction.cc @@ -724,12 +724,10 @@ G4PVPlacement *EncapsulatedPMTConstruction::PlacePMT( G4VSolid * EncapsulatedPMTConstruction::optical_gel_height_subtraction(const std::string &_name) { - double enc_radius = 20.0; // default radius - double enc_thickness = 0.8; G4Sphere *optical_gel_1 = new G4Sphere("optical_gel_1_encapsulation_solid", - 15*CLHEP::cm,///(enc_radius-enc_thickness)*CLHEP::cm, // rmin 20 cm - 20.0*CLHEP::cm,// (enc_radius+enc_thickness)+5 * CLHEP::cm, // rmax: 20.8 cm + 15*CLHEP::cm, + 20.0*CLHEP::cm, 0.5 * CLHEP::pi, CLHEP::twopi, // phi 0., 0.5 * CLHEP::pi); G4Tubs *gel_subtract = From 20edfe9eeaf88a03d01679f38df5325ba757bc3e Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Tue, 15 Apr 2025 18:17:51 +0100 Subject: [PATCH 13/52] Added encapsulation --- ratdb/PMT.ratdb | 481 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 481 insertions(+) diff --git a/ratdb/PMT.ratdb b/ratdb/PMT.ratdb index 9256ca2c..069d8716 100644 --- a/ratdb/PMT.ratdb +++ b/ratdb/PMT.ratdb @@ -489,6 +489,487 @@ z_origin: [ -40.0, 0.0, 0.0, 40.0, -142.0 ], noise_rate: 10000.0, // Hz } +{ +name: "PMT", +index: "r5912", +valid_begin: [0,0], +valid_end: [0,0], + +construction: "toroidal", + +dynode_material: "stainless_steel", +glass_material: "hamamatsu_borosilicate_glass", +pmt_vacuum_material: "pmt_vacuum", // dilute air +photocathode_surface: "photocathode", +mirror_surface: "mirror", +dynode_surface: "stainless_steel", + +dynode_radius: 27.5, // mm +dynode_top: -30.0, // mm +wall_thickness: 3.0, // mm + +z_edge: [ 75.00, 53.06, 0.00, -53.06, -73.86, -85.00, -215.00], +rho_edge: [ 0.00, 72.58, 101.00, 72.58, 44.32, 42.00, 42.00], +z_origin: [-56.00, 0.00, 0.00, 56.00, -85.00, -215.00], + +noise_rate: 10000.0, // Hz +} + +{ +name: "PMT", +index: "r14688", +valid_begin: [0,0], +valid_end: [0,0], + +construction: "toroidal", + +dynode_material: "stainless_steel", +glass_material: "hamamatsu_borosilicate_glass", +pmt_vacuum_material: "pmt_vacuum", // dilute air +photocathode_surface: "photocathode_r14688", +mirror_surface: "mirror", +dynode_surface: "stainless_steel", + +dynode_radius: 27.5, // mm +dynode_top: -30.0, // mm +wall_thickness: 3.0, // mm + +z_edge: [ 75.00, 53.06, 0.00, -53.06, -73.86, -85.00, -215.00], +rho_edge: [ 0.00, 72.58, 101.00, 72.58, 44.32, 42.00, 42.00], +z_origin: [-56.00, 0.00, 0.00, 56.00, -85.00, -215.00], + +noise_rate: 10000.0, // Hz +} + +{ +name: "PMT", +index: "r1408", +valid_begin: [0,0], +valid_end: [0,0], + +construction: "toroidal", + +dynode_material: "stainless_steel", +glass_material: "hamamatsu_borosilicate_glass", +pmt_vacuum_material: "pmt_vacuum", // dilute air +photocathode_surface: "photocathode_R1408", +mirror_surface: "mirror", +dynode_surface: "stainless_steel", + +dynode_radius: 27.5, // mm +dynode_top: -30.0, // mm +wall_thickness: 3.0, // mm + +z_edge: [ 75.00, 53.06, 0.00, -53.06, -73.86, -85.00, -215.00], +rho_edge: [ 0.00, 72.58, 101.00, 72.58, 44.32, 42.00, 42.00], +z_origin: [-56.00, 0.00, 0.00, 56.00, -85.00, -215.00], + +noise_rate: 10000.0, // Hz +} + +{ + +name: "PMT", +index: "r1408_rev", +valid_begin: [0,0], +valid_end: [0,0], + +construction: "revolution", + +dynode_material: "stainless_steel", +glass_material: "hamamatsu_borosilicate_glass", +pmt_vacuum_material: "pmt_vacuum", +photocathode_surface: "photocathode_R1408", +mirror_surface: "mirror", +dynode_surface: "stainless_steel", + +dynode_radius: 27.5, // mm +dynode_top: -30.0, // mm +dynode_height: 182.0, // mm + +"rho_inner" : [ + 0.0, 8.497172075619783, 17.34521741993582, 25.580856472067005, 34.590617694593604, 45.12735249834655, 57.565386429334886, 65.9965008593112, 75.18335667546589, 84.10548316917038, 90.81884441996348, 95.60624053875435, 98.81710731995523, 99.30948129910692, 99.2828034995419, 98.5793846645956, 96.65227304152548, 92.48669849460822, 87.45978193883504, 80.1578523136181, 70.96737375531528, 63.37636262131124, 59.12545487412577, 54.07230583102999, 50.300144855194134, 46.11181742355254, 42.8014721263096, 41.30212377071635, 40.1263492719929, 39.19327132685637, 38.88131102215652, 39.0 +], +"z_inner" : [ + 72.0, 71.45434942723473, 70.66037661659678, 69.20094682621948, 67.13525319654228, 63.24351751187053, 58.6098782795783, 53.84251239690675, 48.06541189846085, 39.7699235677601, 31.508164887912518, 21.17848443941654, 9.954178769927344, 0.922769096259546, 0, -7.691261047697814, -17.43689618240154, -26.21971645247576, -34.15498626710645, -41.72068464771082, -49.140552823239176, -55.2707445397905, -58.41852049267171, -61.84016029477506, -64.27209061954491, -66.80558671460713, -70.80942321511729, -73.89719148996345, -76.42676873527704, -79.69068154540452, -83.98233146805481, -212.0 +], +"rho_edge" : [ + 0.0, 8.712933954276037, 17.682383102831878, 26.396184965659987, 35.36669489133502, 46.38894063411421, 58.692894439740336, 67.66610452535515, 76.89611910810048, 86.38515617649826, 93.31135572490356, 98.44590271897638, 101.78735064446326, 102.3090601185436, 102.28468159679329, 101.54819362122495, 99.50667983817857, 95.15884372941952, 89.78513971210839, 82.10472763195033, 72.88638159751623, 65.20442656882115, 60.850997271615384, 55.72908316868944, 51.88762348292407, 47.78984147144604, 45.545441716059834, 43.97335591306801, 42.92543042619249, 42.14037538808919, 41.88125882020886, 42.0 +], +"z_edge" : [ + 75.0, 74.44658050315763, 73.64136962267332, 72.08802830195503, 70.03313245294652, 65.96535427694118, 61.3899368556647, 56.334985786600726, 50.52842729617066, 41.720075095119114, 33.17771195066513, 22.146120064131054, 10.375669687048259, 0.8725007564532348, 0, -8.122739180443006, -18.360130626744137, -27.583402576213643, -36.05043112947445, -44.00315622362777, -51.44650358194397, -57.64943792142137, -60.872599430779815, -64.34117785837154, -66.81765766963429, -69.29239899033104, -72.02211892737404, -75.26266534239247, -77.50618741781162, -80.25155376994857, -84.00002917866578, -215.0 +] + +noise_rate: 10000.0, // Hz +} + +{ +name: "PMT", +index: "r11065", +valid_begin: [0,0], +valid_end: [0,0], + +construction: "toroidal", + +dynode_material: "stainless_steel", +glass_material: "quartz", +pmt_vacuum_material: "pmt_vacuum", // dilute air +photocathode_surface: "photocathode_R11065", +mirror_surface: "mirror", +dynode_surface: "stainless_steel", + +dynode_radius: 23.0, // mm +dynode_top: -30.0, // mm +wall_thickness: 3.0, // mm + +z_edge: [ 4.020, 1.00, 0.00, -16.75, -30.00, -32.00, -119.0], // rough guess. Photocathode details are wrong +rho_edge: [ 38.0 , 38.0, 38.0, 38.0, 26.65, 26.65, 26.65], // this assumes that the photocathode covers the entire front face of the PMT +z_origin: [ -1000000.00, 0.00, 0.00, 10000.00, 31.00, 0.00], // and wraps back another 1mm, in reality the photocathode diameter is ~64mm + +noise_rate: 10000.0, // Hz +} + +{ +name: "PMT", +index: "r11780_hqe", +valid_begin: [0,0], +valid_end: [0,0], + +construction: "toroidal", + +dynode_material: "stainless_steel", +glass_material: "hamamatsu_borosilicate_glass", +pmt_vacuum_material: "pmt_vacuum", +photocathode_surface: "photocathode_R11780", +mirror_surface: "mirror", +dynode_surface: "stainless_steel", + +dynode_radius: 41.5, // mm +dynode_top: -46.0, // mm +wall_thickness: 3.0, // mm + +z_edge: [112.50, 79.59, 0.75, 0.00, -79.59, -119.79, -127.50, -285.0], +rho_edge: [0.00, 108.87, 151.35, 151.50, 108.87, 66.48, 63.0, 63.0], +z_origin: [-84.00, 0.00, 0.00, 0.00, 84.00, -127.5, -285.0], + +noise_rate: 10000.0, // Hz +} + +// measurements done for Eos +{ +name: "PMT", +index: "r11780_hqe_rev", +valid_begin: [0,0], +valid_end: [0,0], + +construction: "revolution", + +dynode_material: "stainless_steel", +glass_material: "hamamatsu_borosilicate_glass", +pmt_vacuum_material: "pmt_vacuum", +photocathode_surface: "photocathode_R11780", +mirror_surface: "mirror", +dynode_surface: "stainless_steel", + +dynode_radius: 41.5, // mm +dynode_top: -46.0, // mm +dynode_height: 150.0, // mm + +"rho_inner" : [ + 0.22406952, 49.41586494, 74.32942867, 91.6924572 ,105.40891647, + 116.5253067 ,125.95097542,134.07471657,140.48682213,145.20755768, + 148.17373276,149.23321724,148.05885315,144.99187469,141.278162 , + 135.10116577,127.29058266,115.85426331,102.36156464, 84.29887772, + 72.99864769, 66.33180141, 62.50701427, 60.66390514, 60.49633026, + 60.49714565, 60.49758911, 60.49818039, 59.12582397, 59.12582397, + 55.11705399, 44.07295704 +], +"z_inner" : [ + 112.47871399, 104.98492241, 94.99014854, 84.99956131, 74.92696762, + 64.99531269, 54.9890852 , 44.82691765, 34.56035614, 23.8878727 , + 12.9626441 , -4.73298669, -13.56298566, -24.48335648, -33.02436829, + -43.37096691, -53.20465088, -64.18354988, -74.06761169, -84.5257473 , + -94.70726013,-104.81655121,-114.61408615,-124.97786522,-129.18772697, + -140.7053566 ,-152.22356796,-163.74206543,-170. ,-184.96992111, + -193.93230438,-204.97812271 +], +"rho_edge" : [ + 0.23781043, 11.17022395, 31.30234957, 41.80825233, 51.18708134, + 58.45221996, 64.86060619, 70.79629421, 80.62670708, 89.39595222, + 97.02996254,103.82561684,115.61426163,125.51324844,133.92790794, + 140.70964813,146.01588249,149.48794365,151.70327187,152.39591599, + 152.39830017,151.66875839,149.48737144,145.99025726,140.61699867, + 133.71498108,124.87910271,111.77845001, 96.61113739, 81.48579597, + 72.58569717, 67.1009922 , 64.28603172, 63.49999428, 63.49999428, + 63.49998474, 63.49998951, 63.50000381, 62.95897007, 59.72821712, + 53.84859562, 40.05074024 +], +"z_edge" : [ + 115.47869682, 115.10863304, 112.56685257, 110.24722099, 107.57553101, + 105.09346008, 102.59584427, 100.00752449, 95.10297775, 90.0252533 , + 85.00519753, 80.01614571, 70.00720978, 60.00106812, 50.00823975, + 40.24404526, 30.01494884, 20.38056135, 10.01260996, 0.15422568, + -0.31608187, -10.22389054, -20.38113356, -30.07738113, -40.39454937, + -50.26548386, -60.0572443 , -71.22252464, -81.03292465, -90.4088974 , + -100.19306183,-110.39588928,-120.27736664,-135. ,-140.7053566 , + -152.22385406,-163.74235153,-175.25999069,-181.64325714,-191.79096222, + -200.60325623,-210.42926788 +] + +noise_rate: 10000.0, // Hz +} + +{ +name: "PMT", +index: "r7081_hqe", +valid_begin: [0,0], +valid_end: [0,0], + +construction: "toroidal", + +dynode_material: "stainless_steel", +glass_material: "hamamatsu_borosilicate_glass", +pmt_vacuum_material: "pmt_vacuum", +photocathode_surface: "photocathode_R7081HQE", +mirror_surface: "mirror", +dynode_surface: "stainless_steel", + +dynode_radius: 27.5, // mm +dynode_top: -5.9, // mm +wall_thickness: 3.0, // mm + +z_edge: [ 96.7, 40.0, 0.0, -40.0, -90.0, -142.0 ], +rho_edge: [ 0.0, 111.0, 130.0, 111.0, 42.25, 42.25 ], +z_origin: [ -40.0, 0.0, 0.0, 40.0, -142.0 ], + +noise_rate: 10000.0, // Hz +} + +{ +name: "PMT", +index: "r7081", +valid_begin: [0,0], +valid_end: [0,0], + +construction: "toroidal", + +dynode_material: "stainless_steel", +glass_material: "hamamatsu_borosilicate_glass", +pmt_vacuum_material: "pmt_vacuum", +photocathode_surface: "photocathode_R7081", +mirror_surface: "mirror", +dynode_surface: "stainless_steel", + +dynode_radius: 27.5, // mm +dynode_top: -5.9, // mm +wall_thickness: 3.0, // mm + +z_edge: [ 96.7, 40.0, 0.0, -40.0, -90.0, -142.0 ], +rho_edge: [ 0.0, 111.0, 130.0, 111.0, 42.25, 42.25 ], +z_origin: [ -40.0, 0.0, 0.0, 40.0, -142.0 ], + +noise_rate: 10000.0, // Hz +} + + +{ +name: "PMT", +index: "r7081_rev", +valid_begin: [0,0], +valid_end: [0,0], + +construction: "revolution", + +dynode_material: "stainless_steel", +glass_material: "hamamatsu_borosilicate_glass", +pmt_vacuum_material: "pmt_vacuum", +photocathode_surface: "photocathode_R7081", +mirror_surface: "mirror", +dynode_surface: "stainless_steel", + +dynode_radius: 27.5, // mm +dynode_top: -43.7, // mm +dynode_height: 100.0, // mm + +//0.05rad face density +"rho_inner" : [ + 2.501690401754149, 9.172900600188227, 15.827826891209853, 22.443259412429057, 29.002604377502625, 35.48946014113348, 41.88761148855203, 48.181065933768366, 54.35409295441039, 60.39126312725447, 66.27748663718998, 71.99805097337008, 77.5386576944237, 82.88545816333328, 88.02508815999704, 92.94470128387604, 97.63200106279011, 102.07527168741201, 106.26340729451667, 110.18593972574507, 114.58025685703835, 116.6457336287988, 119.42921005937527, 121.44137628413552, 122.65123712458202, 123.1892796112572, 123.5, 123.20826612920352, 122.45409716848, 121.30060662687725, 119.54191360617526, 117.09024829771481, 113.82378257072736, 109.66097932799293, 102.62612269489755, 52.42170409044925, 45.93413443486852, 41.68177216362357, 40.15988482987869, 39.48418801210443, 39.3327, 39.00422132376172, 38.10955066507895, 36.21487231522765, 31.6456328901129 +], +"z_inner" : [ + 89.9766010440378, 89.68496127760612, 89.05982033702337, 88.1028455950343, 86.81643168322714, 85.20379443170408, 83.26896472675583, 81.01677868468974, 78.45286561969525, 75.58363399014434, 72.41625538681959, 68.9586466101737, 65.21944988360431, 61.20801125297499, 56.93435722666859, 52.40916971471062, 47.64375932966273, 42.65003711603731, 37.44048477892932, 32.02812348628791, 25.99684622047763, 23.20659240454441, 18.78773106851574, 14.056471664957295, 9.703270523641883, 4.63010816525746, 0.0, -4.6706796744239085, -9.466502128585988, -14.142695574352029, -18.787686078122306, -23.549751881872574, -28.20682241195521, -32.748162217503896, -37.460131376784545, -67.3812156555737, -72.74839317227139, -78.78763515794739, -84.41498380797144, -89.7032587940464, -140.0, -142.14264287772798, -145.14264287772843, -146.88499849275922, -149.26126301065534 +], +"rho_edge" : [ + 2.5508485939427668, 9.378623545656492, 16.18295682279789, 22.946841135803343, 29.65337029645304, 36.28578147453836, 42.82749709620691, 49.262166279264314, 55.573705701863865, 61.74633980243515, 67.76464021037252, 73.6135643089263, 79.27849283391097, 84.74526641425177, 90.00022096303854, 95.03022183062674, 99.82269663442116, 104.36566668328497, 108.64777691802907, 112.6583242931465, 116.81349999999999, 119.05066381418094, 122.1733682249623, 124.28913931517786, 125.63652632629436, 126.16638895264707, 126.5, 126.1901360329992, 125.40627941576703, 124.17550299401198, 122.28605189620758, 119.71642049234863, 116.22888426041406, 111.64320701454234, 104.22270259481036, 53.88525065868264, 47.916624458380845, 44.425887957418496, 43.10229133732535, 42.469476047904195, 42.3327, 41.879101976047906, 40.98443131736527, 38.34249272882807, 32.8701 +], +"z_edge" : [ + 92.97619826235575, 92.67789931066125, 92.03872663492706, 91.06027783396783, 89.7449985202197, 88.09617620698276, 86.1179320913501, 83.81521075336114, 81.1937677971268, 78.2601554648165, 75.02170625946532, 71.48651461753485, 67.66341667703774, 63.56196819179428, 59.19242064702449, 54.56569563597395, 49.69335756161847, 44.58758473167934, 39.2611389191963, 33.72733346474121, 28.0000000000000140, 25.0, 20.0, 15.0, 10.0, 5.0, 0.0, -5.0, -10.0, -15.0, -20.0, -25.0, -30.0, -35.0, -40.0, -70.0, -75.0, -80.0, -85.0, -90.0, -140.0, -143.0, -146.0, -149.0, -152.0 +] + +noise_rate: 10000.0, // Hz +} + +{ +name: "PMT", +index: "r14374_rev", +valid_begin: [0,0], +valid_end: [0,0], + +construction: "revolution", + +dynode_material: "stainless_steel", +glass_material: "hamamatsu_borosilicate_glass", +pmt_vacuum_material: "pmt_vacuum", +photocathode_surface: "photocathode_R1408", //used the 1408 photocathode in SNO+ rat +mirror_surface: "mirror", +dynode_surface: "stainless_steel", + +// made up... +dynode_radius: 8.25, // mm +dynode_top: -12.0, // mm +dynode_height: 30.0, // mm + +"rho_inner" : [ +0.750507120526, 2.75187018006, 4.74834806736, 6.73297782373, 8.70078131325, 10.6468380423, 12.5662834466, 14.4543197801, 16.3062278863, 18.1173789382, 19.8832459912, 21.599415292, 23.2615973083, 24.865637449, 26.407526448, 27.8834103852, 29.2896003188, 30.6225815062, 31.8790221884, 33.0557819177, 34.3740770571, 34.9937200886, 35.8287630178, 36.4324128852, 36.7953711374, 36.9567838834, 37.05, 36.9624798388, 36.7362291505, 36.3901819881, 35.8625740819, 35.1270744893, 34.1471347712, 32.8982937984, 30.7878368085, 15.7265112271, 13.7802403305, 12.5045316491, 12.047965449, 11.8452564036, 11.79981, 11.7012663971, 11.4328651995, 10.8644616946, 9.49368986703, +], +"z_inner" : [ +26.9929803132, 26.9054883833, 26.7179461011, 26.4308536785, 26.044929505, 25.5611383295, 24.980689418, 24.3050336054, 23.5358596859, 22.675090197, 21.724876616, 20.6875939831, 19.5658349651, 18.3624033759, 17.080307168, 15.7227509144, 14.2931277989, 12.7950111348, 11.2321454337, 9.60843704589, 7.79905386614, 6.96197772136, 5.63631932055, 4.21694149949, 2.91098115709, 1.38903244958, 0.0, -1.40120390233, -2.83995063858, -4.24280867231, -5.63630582344, -7.06492556456, -8.46204672359, -9.82444866525, -11.238039413, -20.2143646967, -21.8245179517, -23.6362905474, -25.3244951424, -26.9109776382, -42.0, -42.6427928633, -43.5427928633, -44.0654995478, -44.7783789032, +], +"rho_edge" : [ +0.765254578183, 2.8135870637, 4.85488704684, 6.88405234074, 8.89601108894, 10.8857344424, 12.8482491289, 14.7786498838, 16.6721117106, 18.5239019407, 20.3293920631, 22.0840692927, 23.7835478502, 25.4235799243, 27.0000662889, 28.5090665492, 29.9468089903, 31.309700005, 32.5943330754, 33.7974972879, 35.04405, 35.7151991443, 36.6520104675, 37.2867417946, 37.6909578979, 37.8499166858, 37.95, 37.8570408099, 37.6218838247, 37.2526508982, 36.6858155689, 35.9149261477, 34.8686652781, 33.4929621044, 31.2668107784, 16.1655751976, 14.3749873375, 13.3277663872, 12.9306874012, 12.7408428144, 12.69981, 12.5637305928, 12.2953293952, 11.5027478186, 9.86103, +], +"z_edge" : [ +27.8928594787, 27.8033697932, 27.6116179905, 27.3180833502, 26.9234995561, 26.4288528621, 25.8353796274, 25.144563226, 24.3581303391, 23.4780466394, 22.5065118778, 21.4459543853, 20.2990250031, 19.0685904575, 17.7577261941, 16.3697086908, 14.9080072685, 13.3762754195, 11.7783416758, 10.1182000394, 8.4, 7.5, 6.0, 4.5, 3.0, 1.5, 0.0, -1.5, -3.0, -4.5, -6.0, -7.5, -9.0, -10.5, -12.0, -21.0, -22.5, -24.0, -25.5, -27.0, -42.0, -42.9, -43.8, -44.7, -45.6, +] + +noise_rate: 10000.0, // Hz +} + +{ +name: "PMT", +index: "et9390b", +valid_begin: [0,0], +valid_end: [0,0], + +construction: "toroidal", + +dynode_material: "stainless_steel", +glass_material: "borosilicate_glass", +pmt_vacuum_material: "pmt_vacuum", // dilute air +photocathode_surface: "photocathode_et9390b", +mirror_surface: "mirror", +dynode_surface: "stainless_steel", + +dynode_radius: 2.0, // wild guess in mm +dynode_top: -100.375, // wild guess in mm was -20.625 +wall_thickness: 3.0, // wild guess in mm +z_edge: [ 4.020, 1.00, 0.00, -42.75, -84.00, -85.00, -150.00], // taken from PMT documentation. Photocathode details are wrong +rho_edge: [ 67.50 , 67.50, 67.50, 67.50, 25.75, 25.75, 25.75], // this assumes that the photocathode covers the entire front face of the PMT +z_origin: [ -1000000.00, 0.00, 0.00, 10000.00, 84.50, 0.00], // and wraps back another 1mm, in reality the photocathode diameter is ~115mm + +noise_rate: 10000.0, // Hz +} + +{ +name: "PMT", +index: "h11934", + +valid_begin: [0,0], +valid_end: [0,0], + +construction: "cubic", + +case_material: "acrylic_white", +glass_material: "hamamatsu_borosilicate_glass", +pmt_vacuum_material: "pmt_vacuum", +photocathode_surface: "photocathode_H11934", +mirror_surface: "mirror", + +case_thickness: 2.0, // mm +glass_thickness: 1.0, // mm + +pmt_width: 15.0, //mm +photocathode_width: 11.5, //mm + +noise_rate: 10000.0, // Hz +} + +{ +name: "PMT", +index: "lappd", + +valid_begin: [0,0], +valid_end: [0,0], + +construction: "lappd", + +glass_material: "glass", +pmt_vacuum_material: "pmt_vacuum", +photocathode_surface: "photocathode_lappd", + +glass_thickness: 1.0, // mm + +width: 105.5, //mm +thick: 9.25, //mm + +noise_rate: 10000.0, // Hz +} + +{ +name: "PMT", +index: "r7081pe", +valid_begin: [0,0], +valid_end: [0,0], + +construction: "toroidal", + +dynode_material: "stainless_steel", +glass_material: "hamamatsu_borosilicate_glass", +pmt_vacuum_material: "pmt_vacuum", +photocathode_surface: "photocathode_R7081", +photocathode_MINrho: 110.0, +photocathode_MAXrho: 126.5, +mirror_surface: "mirror", +dynode_surface: "stainless_steel", + +dynode_radius: 27.5, // mm +dynode_top: -5.9, // mm +wall_thickness: 3.0, // mm + +z_edge: [ 96.7, 40.0, 0.0, -40.0, -90.0, -142.0 ], +rho_edge: [ 0.0, 111.0, 126.5, 111.0, 42.25, 42.25 ], +z_origin: [ -40.0, 0.0, 0.0, 40.0, -142.0 ], + +noise_rate: 10000.0, // Hz +} + +{ +name: "PMT", +index: "r3600", +valid_begin: [0,0], +valid_end: [0,0], +construction: "toroidal", + +dynode_material: "stainless_steel", +glass_material: "hamamatsu_borosilicate_glass", +pmt_vacuum_material: "pmt_vacuum", +photocathode_surface: "photocathode_R3600", +photocathode_MINrho: 230.0, +photocathode_MAXrho: 254.0, +mirror_surface: "mirror", +dynode_surface: "stainless_steel", + +dynode_radius: 27.5, // mm +dynode_top: -5.9, // mm +wall_thickness: 4.0, // mm + +z_edge: [ 194.2, 92.0, 0.0, -92.0, -207.0, -300.0 ], +rho_edge: [ 0.0, 200.0, 254.0, 200.0, 127.5, 127.5 ], +z_origin: [ -60.0, 0.0, 0.0, 60.0, -300.0 ], + +noise_rate: 10000.0, // Hz +} + + { From 5cb7ab103b759a8c4c32b1b28678b4c59e9ee897 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Tue, 15 Apr 2025 18:55:43 +0100 Subject: [PATCH 14/52] Added encapsulations --- ratdb/OPTICS.ratdb | 56 ++++- ratdb/PMT.ratdb | 524 ++------------------------------------------- 2 files changed, 70 insertions(+), 510 deletions(-) diff --git a/ratdb/OPTICS.ratdb b/ratdb/OPTICS.ratdb index 577cf439..74c524f1 100644 --- a/ratdb/OPTICS.ratdb +++ b/ratdb/OPTICS.ratdb @@ -345,8 +345,7 @@ RINDEX_value1: [60.0, 200.0, 300.0, 600.0, 800.0, ], RINDEX_value2: [1.76, 1.76, 1.76, 1.76, 1.76, ], //index of refraction looked up online ABSLENGTH_option: "wavelength", ABSLENGTH_value1: [60.0, 180.0, 200.0, 250.0, 400.0, 1000.0, 2000.0, 3000.0, 4000.0, 5000.0, 7000.0, ], //values calculate from infromation from ceramtech documentation -ABSLENGTH_value2: [0.1e-3, 0.1e-3, 10.0, 44.81, 52.67, 61.53, 61.53, 61.53, 50.39, -28.03,0.1e-3, ], +ABSLENGTH_value2: [0.1e-3, 0.1e-3, 10.0, 44.81, 52.67, 61.53, 61.53, 61.53, 50.39, 28.03, 0.1e-3, ], PROPERTY_LIST: ["RINDEX", "ABSLENGTH", ] } @@ -355,7 +354,28 @@ PROPERTY_LIST: ["RINDEX", "ABSLENGTH", ] { name: "OPTICS", -index: "quartz", +index: "quartz", // fused quartz +valid_begin : [0, 0], +valid_end : [0, 0], +surface: 1, +finish: "ground", +model: "glisur", +type: "dielectric_dielectric", +polish: 0.9, +RINDEX_option: "wavelength", +// Refractive index of Fused silica (fused quartz) from https://refractiveindex.info/?shelf=glass&book=fused_silica&page=Malitson +RINDEX_value1: [60.0, 117.0, 120.0, 140.0, 160.0, 180.0, 200.0, 220.0, 240.0, 260.0, 280.0, 300.0, 320.0, 340.0, 360.0, 380.0, 400.0, 420.0, 440.0, 460.0, 480.0, 500.0, 520.0, 540.0, 560.0, 580.0, 600.0, 620.0, 640.0, 660.0, 680.0, 700.0, 720.0, 740.0, 760.0, 780.0, 800.0, 820.0, 840.0, 860.0, 880.0, 900.0, 920.0, 940.0, 960.0, 980.0, 1000, ], +RINDEX_value2: [5.7982, 5.7982, 2.9406, 1.7966, 1.6479, 1.5853, 1.5505, 1.5285, 1.5133, 1.5024, 1.4942, 1.4878, 1.4827, 1.4787, 1.4753, 1.4725, 1.4701, 1.4681, 1.4663, 1.4648, 1.4635, 1.4623, 1.4613, 1.4603, 1.4595, 1.4587, 1.4580, 1.4574, 1.4568, 1.4563, 1.4558, 1.4553, 1.4549, 1.4544, 1.4540, 1.4537, 1.4533, 1.4530, 1.4527, 1.4523, 1.4520, 1.4518, 1.4515, 1.4512, 1.4509, 1.4507, 1.4504, ], +ABSLENGTH_option: "wavelength", +// Values inherited from "glass" except cutoff set to ~160 nm based on https://www.hamamatsu.com/us/en/support/glossary/w.html +ABSLENGTH_value1: [60.0, 130.0, 160.0, 330.0, 500.0, 600.0, 770.0, 800.0, ], +ABSLENGTH_value2: [0.1e-3, 0.1e-3, 1.0e3, 1.0e3, 2.0e3, 1.0e3, 0.5e3, 0.1e-3, ], +PROPERTY_LIST: ["RINDEX", "ABSLENGTH", ] +} + +{ +name: "OPTICS", +index: "glass", valid_begin : [0, 0], valid_end : [0, 0], surface: 1, @@ -374,7 +394,7 @@ PROPERTY_LIST: ["RINDEX", "ABSLENGTH", ] { name: "OPTICS", -index: "glass", +index: "borosilicate_glass", valid_begin : [0, 0], valid_end : [0, 0], surface: 1, @@ -383,8 +403,31 @@ model: "glisur", type: "dielectric_dielectric", polish: 0.9, RINDEX_option: "wavelength", -RINDEX_value1: [60.0, 200.0, 300.0, 600.0, 800.0, ], -RINDEX_value2: [1.458, 1.458, 1.458, 1.458, 1.458, ], +// Refractive index of Schott BK7 from https://refractiveindex.info/?shelf=popular_glass&book=BK7&page=SCHOTT +// There is no data below 300 nm, so the Sellmeier formulas extrapolated below using an exponential fit. +RINDEX_value1: [60.0, 100.0, 200.0, 300.0, 400.0, 500.0, 600.0, 700.0, 800.0, ], +RINDEX_value2: [1.707, 1.662, 1.589, 1.551, 1.531, 1.521, 1.516, 1.513, 1.512, ], +ABSLENGTH_option: "wavelength", +ABSLENGTH_value1: [60.0, 200.0, 300.0, 330.0, 500.0, 600.0, 770.0, 800.0, ], +ABSLENGTH_value2: [0.1e-3, 0.1e-3, 0.1e-3, 1.0e3, 2.0e3, 1.0e3, 0.5e3, 0.1e-3, ], +PROPERTY_LIST: ["RINDEX", "ABSLENGTH", ] +} + +{ +name: "OPTICS", +index: "hamamatsu_borosilicate_glass", +valid_begin : [0, 0], +valid_end : [0, 0], +surface: 1, +finish: "ground", +model: "glisur", +type: "dielectric_dielectric", +polish: 0.9, +// Refractive index of Schott BK7 from https://refractiveindex.info/?shelf=popular_glass&book=BK7&page=SCHOTT +// There is no data below 300 nm, so the Sellmeier formulas extrapolated below using an exponential fit. +RINDEX_option: "wavelength", +RINDEX_value1: [60.0, 100.0, 200.0, 300.0, 400.0, 500.0, 600.0, 700.0, 800.0, ], +RINDEX_value2: [1.707, 1.662, 1.589, 1.551, 1.531, 1.521, 1.516, 1.513, 1.512, ], ABSLENGTH_option: "wavelength", ABSLENGTH_value1: [60.0, 200.0, 300.0, 330.0, 500.0, 600.0, 770.0, 800.0, ], ABSLENGTH_value2: [0.1e-3, 0.1e-3, 0.1e-3, 1.0e3, 2.0e3, 1.0e3, 0.5e3, 0.1e-3, ], @@ -621,7 +664,6 @@ ABSLENGTH_value2: [1.0e-6, 1.0e-6, 1.0e-6, 5.56e1, 5.56e1, 8.56e1, 8.56e1, 8.56e PROPERTY_LIST: ["RINDEX","ABSLENGTH"] } - { name: "OPTICS", index: "acrylic_polycast", diff --git a/ratdb/PMT.ratdb b/ratdb/PMT.ratdb index 069d8716..d9e26e17 100644 --- a/ratdb/PMT.ratdb +++ b/ratdb/PMT.ratdb @@ -6,497 +6,6 @@ valid_end: [0,0], construction: "toroidal", -dynode_material: "stainless_steel", -glass_material: "glass", -pmt_vacuum_material: "pmt_vacuum", // dilute air -photocathode_surface: "photocathode", -mirror_surface: "mirror", -dynode_surface: "stainless_steel", - -dynode_radius: 27.5, // mm -dynode_top: -30.0, // mm -wall_thickness: 3.0, // mm - -z_edge: [ 75.00, 53.06, 0.00, -53.06, -73.86, -85.00, -215.00], -rho_edge: [ 0.00, 72.58, 101.00, 72.58, 44.32, 42.00, 42.00], -z_origin: [-56.00, 0.00, 0.00, 56.00, -85.00, -215.00], - -noise_rate: 10000.0, // Hz -} - -{ -name: "PMT", -index: "r14688", -valid_begin: [0,0], -valid_end: [0,0], - -construction: "toroidal", - -dynode_material: "stainless_steel", -glass_material: "glass", -pmt_vacuum_material: "pmt_vacuum", // dilute air -photocathode_surface: "photocathode_r14688", -mirror_surface: "mirror", -dynode_surface: "stainless_steel", - -dynode_radius: 27.5, // mm -dynode_top: -30.0, // mm -wall_thickness: 3.0, // mm - -z_edge: [ 75.00, 53.06, 0.00, -53.06, -73.86, -85.00, -215.00], -rho_edge: [ 0.00, 72.58, 101.00, 72.58, 44.32, 42.00, 42.00], -z_origin: [-56.00, 0.00, 0.00, 56.00, -85.00, -215.00], - -noise_rate: 10000.0, // Hz -} - -{ -name: "PMT", -index: "r1408", -valid_begin: [0,0], -valid_end: [0,0], - -construction: "toroidal", - -dynode_material: "stainless_steel", -glass_material: "glass", -pmt_vacuum_material: "pmt_vacuum", // dilute air -photocathode_surface: "photocathode_R1408", -mirror_surface: "mirror", -dynode_surface: "stainless_steel", - -dynode_radius: 27.5, // mm -dynode_top: -30.0, // mm -wall_thickness: 3.0, // mm - -z_edge: [ 75.00, 53.06, 0.00, -53.06, -73.86, -85.00, -215.00], -rho_edge: [ 0.00, 72.58, 101.00, 72.58, 44.32, 42.00, 42.00], -z_origin: [-56.00, 0.00, 0.00, 56.00, -85.00, -215.00], - -noise_rate: 10000.0, // Hz -} - -{ - -name: "PMT", -index: "r1408_rev", -valid_begin: [0,0], -valid_end: [0,0], - -construction: "revolution", - -dynode_material: "stainless_steel", -glass_material: "glass", -pmt_vacuum_material: "pmt_vacuum", -photocathode_surface: "photocathode_R1408", -mirror_surface: "mirror", -dynode_surface: "stainless_steel", - -dynode_radius: 27.5, // mm -dynode_top: -30.0, // mm -dynode_height: 182.0, // mm - -"rho_inner" : [ - 0.0, 8.497172075619783, 17.34521741993582, 25.580856472067005, 34.590617694593604, 45.12735249834655, 57.565386429334886, 65.9965008593112, 75.18335667546589, 84.10548316917038, 90.81884441996348, 95.60624053875435, 98.81710731995523, 99.30948129910692, 99.2828034995419, 98.5793846645956, 96.65227304152548, 92.48669849460822, 87.45978193883504, 80.1578523136181, 70.96737375531528, 63.37636262131124, 59.12545487412577, 54.07230583102999, 50.300144855194134, 46.11181742355254, 42.8014721263096, 41.30212377071635, 40.1263492719929, 39.19327132685637, 38.88131102215652, 39.0 -], -"z_inner" : [ - 72.0, 71.45434942723473, 70.66037661659678, 69.20094682621948, 67.13525319654228, 63.24351751187053, 58.6098782795783, 53.84251239690675, 48.06541189846085, 39.7699235677601, 31.508164887912518, 21.17848443941654, 9.954178769927344, 0.922769096259546, 0, -7.691261047697814, -17.43689618240154, -26.21971645247576, -34.15498626710645, -41.72068464771082, -49.140552823239176, -55.2707445397905, -58.41852049267171, -61.84016029477506, -64.27209061954491, -66.80558671460713, -70.80942321511729, -73.89719148996345, -76.42676873527704, -79.69068154540452, -83.98233146805481, -212.0 -], -"rho_edge" : [ - 0.0, 8.712933954276037, 17.682383102831878, 26.396184965659987, 35.36669489133502, 46.38894063411421, 58.692894439740336, 67.66610452535515, 76.89611910810048, 86.38515617649826, 93.31135572490356, 98.44590271897638, 101.78735064446326, 102.3090601185436, 102.28468159679329, 101.54819362122495, 99.50667983817857, 95.15884372941952, 89.78513971210839, 82.10472763195033, 72.88638159751623, 65.20442656882115, 60.850997271615384, 55.72908316868944, 51.88762348292407, 47.78984147144604, 45.545441716059834, 43.97335591306801, 42.92543042619249, 42.14037538808919, 41.88125882020886, 42.0 -], -"z_edge" : [ - 75.0, 74.44658050315763, 73.64136962267332, 72.08802830195503, 70.03313245294652, 65.96535427694118, 61.3899368556647, 56.334985786600726, 50.52842729617066, 41.720075095119114, 33.17771195066513, 22.146120064131054, 10.375669687048259, 0.8725007564532348, 0, -8.122739180443006, -18.360130626744137, -27.583402576213643, -36.05043112947445, -44.00315622362777, -51.44650358194397, -57.64943792142137, -60.872599430779815, -64.34117785837154, -66.81765766963429, -69.29239899033104, -72.02211892737404, -75.26266534239247, -77.50618741781162, -80.25155376994857, -84.00002917866578, -215.0 -] - -noise_rate: 10000.0, // Hz -} - -{ -name: "PMT", -index: "r11065", -valid_begin: [0,0], -valid_end: [0,0], - -construction: "toroidal", - -dynode_material: "stainless_steel", -glass_material: "quartz", -pmt_vacuum_material: "pmt_vacuum", // dilute air -photocathode_surface: "photocathode_R11065", -mirror_surface: "mirror", -dynode_surface: "stainless_steel", - -dynode_radius: 23.0, // mm -dynode_top: -30.0, // mm -wall_thickness: 3.0, // mm - -z_edge: [ 4.020, 1.00, 0.00, -16.75, -30.00, -32.00, -119.0], // rough guess. Photocathode details are wrong -rho_edge: [ 38.0 , 38.0, 38.0, 38.0, 26.65, 26.65, 26.65], // this assumes that the photocathode covers the entire front face of the PMT -z_origin: [ -1000000.00, 0.00, 0.00, 10000.00, 31.00, 0.00], // and wraps back another 1mm, in reality the photocathode diameter is ~64mm - -noise_rate: 10000.0, // Hz -} - -{ -name: "PMT", -index: "r11780_hqe", -valid_begin: [0,0], -valid_end: [0,0], - -construction: "toroidal", - -dynode_material: "stainless_steel", -glass_material: "glass", -pmt_vacuum_material: "pmt_vacuum", -photocathode_surface: "photocathode_R11780", -mirror_surface: "mirror", -dynode_surface: "stainless_steel", - -dynode_radius: 41.5, // mm -dynode_top: -46.0, // mm -wall_thickness: 3.0, // mm - -z_edge: [112.50, 79.59, 0.75, 0.00, -79.59, -119.79, -127.50, -285.0], -rho_edge: [0.00, 108.87, 151.35, 151.50, 108.87, 66.48, 63.0, 63.0], -z_origin: [-84.00, 0.00, 0.00, 0.00, 84.00, -127.5, -285.0], - -noise_rate: 10000.0, // Hz -} - -// measurements done for Eos -{ -name: "PMT", -index: "r11780_hqe_rev", -valid_begin: [0,0], -valid_end: [0,0], - -construction: "revolution", - -dynode_material: "stainless_steel", -glass_material: "glass", -pmt_vacuum_material: "pmt_vacuum", -photocathode_surface: "photocathode_R11780", -mirror_surface: "mirror", -dynode_surface: "stainless_steel", - -dynode_radius: 41.5, // mm -dynode_top: -46.0, // mm -dynode_height: 150.0, // mm - -"rho_inner" : [ - 0.22406952, 49.41586494, 74.32942867, 91.6924572 ,105.40891647, - 116.5253067 ,125.95097542,134.07471657,140.48682213,145.20755768, - 148.17373276,149.23321724,148.05885315,144.99187469,141.278162 , - 135.10116577,127.29058266,115.85426331,102.36156464, 84.29887772, - 72.99864769, 66.33180141, 62.50701427, 60.66390514, 60.49633026, - 60.49714565, 60.49758911, 60.49818039, 59.12582397, 59.12582397, - 55.11705399, 44.07295704 -], -"z_inner" : [ - 112.47871399, 104.98492241, 94.99014854, 84.99956131, 74.92696762, - 64.99531269, 54.9890852 , 44.82691765, 34.56035614, 23.8878727 , - 12.9626441 , -4.73298669, -13.56298566, -24.48335648, -33.02436829, - -43.37096691, -53.20465088, -64.18354988, -74.06761169, -84.5257473 , - -94.70726013,-104.81655121,-114.61408615,-124.97786522,-129.18772697, - -140.7053566 ,-152.22356796,-163.74206543,-170. ,-184.96992111, - -193.93230438,-204.97812271 -], -"rho_edge" : [ - 0.23781043, 11.17022395, 31.30234957, 41.80825233, 51.18708134, - 58.45221996, 64.86060619, 70.79629421, 80.62670708, 89.39595222, - 97.02996254,103.82561684,115.61426163,125.51324844,133.92790794, - 140.70964813,146.01588249,149.48794365,151.70327187,152.39591599, - 152.39830017,151.66875839,149.48737144,145.99025726,140.61699867, - 133.71498108,124.87910271,111.77845001, 96.61113739, 81.48579597, - 72.58569717, 67.1009922 , 64.28603172, 63.49999428, 63.49999428, - 63.49998474, 63.49998951, 63.50000381, 62.95897007, 59.72821712, - 53.84859562, 40.05074024 -], -"z_edge" : [ - 115.47869682, 115.10863304, 112.56685257, 110.24722099, 107.57553101, - 105.09346008, 102.59584427, 100.00752449, 95.10297775, 90.0252533 , - 85.00519753, 80.01614571, 70.00720978, 60.00106812, 50.00823975, - 40.24404526, 30.01494884, 20.38056135, 10.01260996, 0.15422568, - -0.31608187, -10.22389054, -20.38113356, -30.07738113, -40.39454937, - -50.26548386, -60.0572443 , -71.22252464, -81.03292465, -90.4088974 , - -100.19306183,-110.39588928,-120.27736664,-135. ,-140.7053566 , - -152.22385406,-163.74235153,-175.25999069,-181.64325714,-191.79096222, - -200.60325623,-210.42926788 -] - -noise_rate: 10000.0, // Hz -} - -{ -name: "PMT", -index: "r7081_hqe", -valid_begin: [0,0], -valid_end: [0,0], - -construction: "toroidal", - -dynode_material: "stainless_steel", -glass_material: "glass", -pmt_vacuum_material: "pmt_vacuum", -photocathode_surface: "photocathode_R7081HQE", -mirror_surface: "mirror", -dynode_surface: "stainless_steel", - -dynode_radius: 27.5, // mm -dynode_top: -5.9, // mm -wall_thickness: 3.0, // mm - -z_edge: [ 96.7, 40.0, 0.0, -40.0, -90.0, -142.0 ], -rho_edge: [ 0.0, 111.0, 130.0, 111.0, 42.25, 42.25 ], -z_origin: [ -40.0, 0.0, 0.0, 40.0, -142.0 ], - -noise_rate: 10000.0, // Hz -} - -{ -name: "PMT", -index: "r7081", -valid_begin: [0,0], -valid_end: [0,0], - -construction: "toroidal", - -dynode_material: "stainless_steel", -glass_material: "glass", -pmt_vacuum_material: "pmt_vacuum", -photocathode_surface: "photocathode_R7081", -mirror_surface: "mirror", -dynode_surface: "stainless_steel", - -dynode_radius: 27.5, // mm -dynode_top: -5.9, // mm -wall_thickness: 3.0, // mm - -z_edge: [ 96.7, 40.0, 0.0, -40.0, -90.0, -142.0 ], -rho_edge: [ 0.0, 111.0, 130.0, 111.0, 42.25, 42.25 ], -z_origin: [ -40.0, 0.0, 0.0, 40.0, -142.0 ], - -noise_rate: 10000.0, // Hz -} - - -{ -name: "PMT", -index: "r7081_rev", -valid_begin: [0,0], -valid_end: [0,0], - -construction: "revolution", - -dynode_material: "stainless_steel", -glass_material: "glass", -pmt_vacuum_material: "pmt_vacuum", -photocathode_surface: "photocathode_R7081", -mirror_surface: "mirror", -dynode_surface: "stainless_steel", - -dynode_radius: 27.5, // mm -dynode_top: -43.7, // mm -dynode_height: 100.0, // mm - -//0.05rad face density -"rho_inner" : [ - 2.501690401754149, 9.172900600188227, 15.827826891209853, 22.443259412429057, 29.002604377502625, 35.48946014113348, 41.88761148855203, 48.181065933768366, 54.35409295441039, 60.39126312725447, 66.27748663718998, 71.99805097337008, 77.5386576944237, 82.88545816333328, 88.02508815999704, 92.94470128387604, 97.63200106279011, 102.07527168741201, 106.26340729451667, 110.18593972574507, 114.58025685703835, 116.6457336287988, 119.42921005937527, 121.44137628413552, 122.65123712458202, 123.1892796112572, 123.5, 123.20826612920352, 122.45409716848, 121.30060662687725, 119.54191360617526, 117.09024829771481, 113.82378257072736, 109.66097932799293, 102.62612269489755, 52.42170409044925, 45.93413443486852, 41.68177216362357, 40.15988482987869, 39.48418801210443, 39.3327, 39.00422132376172, 38.10955066507895, 36.21487231522765, 31.6456328901129 -], -"z_inner" : [ - 89.9766010440378, 89.68496127760612, 89.05982033702337, 88.1028455950343, 86.81643168322714, 85.20379443170408, 83.26896472675583, 81.01677868468974, 78.45286561969525, 75.58363399014434, 72.41625538681959, 68.9586466101737, 65.21944988360431, 61.20801125297499, 56.93435722666859, 52.40916971471062, 47.64375932966273, 42.65003711603731, 37.44048477892932, 32.02812348628791, 25.99684622047763, 23.20659240454441, 18.78773106851574, 14.056471664957295, 9.703270523641883, 4.63010816525746, 0.0, -4.6706796744239085, -9.466502128585988, -14.142695574352029, -18.787686078122306, -23.549751881872574, -28.20682241195521, -32.748162217503896, -37.460131376784545, -67.3812156555737, -72.74839317227139, -78.78763515794739, -84.41498380797144, -89.7032587940464, -140.0, -142.14264287772798, -145.14264287772843, -146.88499849275922, -149.26126301065534 -], -"rho_edge" : [ - 2.5508485939427668, 9.378623545656492, 16.18295682279789, 22.946841135803343, 29.65337029645304, 36.28578147453836, 42.82749709620691, 49.262166279264314, 55.573705701863865, 61.74633980243515, 67.76464021037252, 73.6135643089263, 79.27849283391097, 84.74526641425177, 90.00022096303854, 95.03022183062674, 99.82269663442116, 104.36566668328497, 108.64777691802907, 112.6583242931465, 116.81349999999999, 119.05066381418094, 122.1733682249623, 124.28913931517786, 125.63652632629436, 126.16638895264707, 126.5, 126.1901360329992, 125.40627941576703, 124.17550299401198, 122.28605189620758, 119.71642049234863, 116.22888426041406, 111.64320701454234, 104.22270259481036, 53.88525065868264, 47.916624458380845, 44.425887957418496, 43.10229133732535, 42.469476047904195, 42.3327, 41.879101976047906, 40.98443131736527, 38.34249272882807, 32.8701 -], -"z_edge" : [ - 92.97619826235575, 92.67789931066125, 92.03872663492706, 91.06027783396783, 89.7449985202197, 88.09617620698276, 86.1179320913501, 83.81521075336114, 81.1937677971268, 78.2601554648165, 75.02170625946532, 71.48651461753485, 67.66341667703774, 63.56196819179428, 59.19242064702449, 54.56569563597395, 49.69335756161847, 44.58758473167934, 39.2611389191963, 33.72733346474121, 28.0000000000000140, 25.0, 20.0, 15.0, 10.0, 5.0, 0.0, -5.0, -10.0, -15.0, -20.0, -25.0, -30.0, -35.0, -40.0, -70.0, -75.0, -80.0, -85.0, -90.0, -140.0, -143.0, -146.0, -149.0, -152.0 -] - -noise_rate: 10000.0, // Hz -} - -{ -name: "PMT", -index: "r14374_rev", -valid_begin: [0,0], -valid_end: [0,0], - -construction: "revolution", - -dynode_material: "stainless_steel", -glass_material: "glass", -pmt_vacuum_material: "pmt_vacuum", -photocathode_surface: "photocathode_R1408", //used the 1408 photocathode in SNO+ rat -mirror_surface: "mirror", -dynode_surface: "stainless_steel", - -// made up... -dynode_radius: 8.25, // mm -dynode_top: -12.0, // mm -dynode_height: 30.0, // mm - -"rho_inner" : [ -0.750507120526, 2.75187018006, 4.74834806736, 6.73297782373, 8.70078131325, 10.6468380423, 12.5662834466, 14.4543197801, 16.3062278863, 18.1173789382, 19.8832459912, 21.599415292, 23.2615973083, 24.865637449, 26.407526448, 27.8834103852, 29.2896003188, 30.6225815062, 31.8790221884, 33.0557819177, 34.3740770571, 34.9937200886, 35.8287630178, 36.4324128852, 36.7953711374, 36.9567838834, 37.05, 36.9624798388, 36.7362291505, 36.3901819881, 35.8625740819, 35.1270744893, 34.1471347712, 32.8982937984, 30.7878368085, 15.7265112271, 13.7802403305, 12.5045316491, 12.047965449, 11.8452564036, 11.79981, 11.7012663971, 11.4328651995, 10.8644616946, 9.49368986703, -], -"z_inner" : [ -26.9929803132, 26.9054883833, 26.7179461011, 26.4308536785, 26.044929505, 25.5611383295, 24.980689418, 24.3050336054, 23.5358596859, 22.675090197, 21.724876616, 20.6875939831, 19.5658349651, 18.3624033759, 17.080307168, 15.7227509144, 14.2931277989, 12.7950111348, 11.2321454337, 9.60843704589, 7.79905386614, 6.96197772136, 5.63631932055, 4.21694149949, 2.91098115709, 1.38903244958, 0.0, -1.40120390233, -2.83995063858, -4.24280867231, -5.63630582344, -7.06492556456, -8.46204672359, -9.82444866525, -11.238039413, -20.2143646967, -21.8245179517, -23.6362905474, -25.3244951424, -26.9109776382, -42.0, -42.6427928633, -43.5427928633, -44.0654995478, -44.7783789032, -], -"rho_edge" : [ -0.765254578183, 2.8135870637, 4.85488704684, 6.88405234074, 8.89601108894, 10.8857344424, 12.8482491289, 14.7786498838, 16.6721117106, 18.5239019407, 20.3293920631, 22.0840692927, 23.7835478502, 25.4235799243, 27.0000662889, 28.5090665492, 29.9468089903, 31.309700005, 32.5943330754, 33.7974972879, 35.04405, 35.7151991443, 36.6520104675, 37.2867417946, 37.6909578979, 37.8499166858, 37.95, 37.8570408099, 37.6218838247, 37.2526508982, 36.6858155689, 35.9149261477, 34.8686652781, 33.4929621044, 31.2668107784, 16.1655751976, 14.3749873375, 13.3277663872, 12.9306874012, 12.7408428144, 12.69981, 12.5637305928, 12.2953293952, 11.5027478186, 9.86103, -], -"z_edge" : [ -27.8928594787, 27.8033697932, 27.6116179905, 27.3180833502, 26.9234995561, 26.4288528621, 25.8353796274, 25.144563226, 24.3581303391, 23.4780466394, 22.5065118778, 21.4459543853, 20.2990250031, 19.0685904575, 17.7577261941, 16.3697086908, 14.9080072685, 13.3762754195, 11.7783416758, 10.1182000394, 8.4, 7.5, 6.0, 4.5, 3.0, 1.5, 0.0, -1.5, -3.0, -4.5, -6.0, -7.5, -9.0, -10.5, -12.0, -21.0, -22.5, -24.0, -25.5, -27.0, -42.0, -42.9, -43.8, -44.7, -45.6, -] - -noise_rate: 10000.0, // Hz -} - -{ -name: "PMT", -index: "et9390b", -valid_begin: [0,0], -valid_end: [0,0], - -construction: "toroidal", - -dynode_material: "stainless_steel", -glass_material: "glass", -pmt_vacuum_material: "pmt_vacuum", // dilute air -photocathode_surface: "photocathode_et9390b", -mirror_surface: "mirror", -dynode_surface: "stainless_steel", - -dynode_radius: 2.0, // wild guess in mm -dynode_top: -100.375, // wild guess in mm was -20.625 -wall_thickness: 3.0, // wild guess in mm -z_edge: [ 4.020, 1.00, 0.00, -42.75, -84.00, -85.00, -150.00], // taken from PMT documentation. Photocathode details are wrong -rho_edge: [ 67.50 , 67.50, 67.50, 67.50, 25.75, 25.75, 25.75], // this assumes that the photocathode covers the entire front face of the PMT -z_origin: [ -1000000.00, 0.00, 0.00, 10000.00, 84.50, 0.00], // and wraps back another 1mm, in reality the photocathode diameter is ~115mm - -noise_rate: 10000.0, // Hz -} - -{ -name: "PMT", -index: "h11934", - -valid_begin: [0,0], -valid_end: [0,0], - -construction: "cubic", - -case_material: "acrylic_white", -glass_material: "glass", -pmt_vacuum_material: "pmt_vacuum", -photocathode_surface: "photocathode_H11934", -mirror_surface: "mirror", - -case_thickness: 2.0, // mm -glass_thickness: 1.0, // mm - -pmt_width: 15.0, //mm -photocathode_width: 11.5, //mm - -noise_rate: 10000.0, // Hz -} - -{ -name: "PMT", -index: "lappd", - -valid_begin: [0,0], -valid_end: [0,0], - -construction: "lappd", - -glass_material: "glass", -pmt_vacuum_material: "pmt_vacuum", -photocathode_surface: "photocathode_lappd", - -glass_thickness: 1.0, // mm - -width: 105.5, //mm -thick: 9.25, //mm - -noise_rate: 10000.0, // Hz -} - -{ -name: "PMT", -index: "r7081pe", -valid_begin: [0,0], -valid_end: [0,0], - -construction: "toroidal", - -dynode_material: "stainless_steel", -glass_material: "glass", -pmt_vacuum_material: "pmt_vacuum", -photocathode_surface: "photocathode_R7081", -photocathode_MINrho: 110.0, -photocathode_MAXrho: 126.5, -mirror_surface: "mirror", -dynode_surface: "stainless_steel", - -dynode_radius: 27.5, // mm -dynode_top: -5.9, // mm -wall_thickness: 3.0, // mm - -z_edge: [ 96.7, 40.0, 0.0, -40.0, -90.0, -142.0 ], -rho_edge: [ 0.0, 111.0, 126.5, 111.0, 42.25, 42.25 ], -z_origin: [ -40.0, 0.0, 0.0, 40.0, -142.0 ], - -noise_rate: 10000.0, // Hz -} - -{ -//An encapsulated version of the pmt -name: "PMT", -index: "r7081pe_encapsulated", -valid_begin: [0,0], -valid_end: [0,0], - -construction: "encapsulated", - -dynode_material: "stainless_steel", -glass_material: "glass", -pmt_vacuum_material: "pmt_vacuum", -photocathode_surface: "photocathode_R7081", -photocathode_MINrho: 110.0, -photocathode_MAXrho: 126.5, -mirror_surface: "mirror", -dynode_surface: "stainless_steel", - -inner_encapsulation_material: "glass" -front_encapsulation_material: "nakano_acrylic" -rear_encapsulation_material: "acrylic_black" -metal_flange_material: "stainless_steel" -acrylic_flange_material: "nakano_acrylic" -silica_bag_material: "acrylic_white" -cable_material: "acrylic_black" - - -dynode_radius: 27.5, // mm -dynode_top: -5.9, // mm -wall_thickness: 3.0, // mm - -z_edge: [ 96.7, 40.0, 0.0, -40.0, -90.0, -142.0 ], -rho_edge: [ 0.0, 111.0, 126.5, 111.0, 42.25, 42.25 ], -z_origin: [ -40.0, 0.0, 0.0, 40.0, -142.0 ], - -noise_rate: 10000.0, // Hz -} - -{ -name: "PMT", -index: "r5912", -valid_begin: [0,0], -valid_end: [0,0], - -construction: "toroidal", - dynode_material: "stainless_steel", glass_material: "hamamatsu_borosilicate_glass", pmt_vacuum_material: "pmt_vacuum", // dilute air @@ -943,35 +452,44 @@ noise_rate: 10000.0, // Hz } { +//An encapsulated version of the pmt name: "PMT", -index: "r3600", +index: "r7081pe_encapsulated", valid_begin: [0,0], valid_end: [0,0], -construction: "toroidal", + +construction: "encapsulated", dynode_material: "stainless_steel", glass_material: "hamamatsu_borosilicate_glass", pmt_vacuum_material: "pmt_vacuum", -photocathode_surface: "photocathode_R3600", -photocathode_MINrho: 230.0, -photocathode_MAXrho: 254.0, +photocathode_surface: "photocathode_R7081", +photocathode_MINrho: 110.0, +photocathode_MAXrho: 126.5, mirror_surface: "mirror", dynode_surface: "stainless_steel", +front_encapsulation_material: "nakano_acrylic", +rear_encapsulation_material: "acrylic_black", +metal_flange_material: "stainless_steel", +acrylic_flange_material: "nakano_acrylic", +silica_bag_material: "acrylic_white", +cable_material: "acrylic_black", +inside_encapsulation_material: "air", +optical_gel_material: "optical_grease", + dynode_radius: 27.5, // mm dynode_top: -5.9, // mm -wall_thickness: 4.0, // mm +wall_thickness: 3.0, // mm -z_edge: [ 194.2, 92.0, 0.0, -92.0, -207.0, -300.0 ], -rho_edge: [ 0.0, 200.0, 254.0, 200.0, 127.5, 127.5 ], -z_origin: [ -60.0, 0.0, 0.0, 60.0, -300.0 ], +z_edge: [ 96.7, 40.0, 0.0, -40.0, -90.0, -142.0 ], +rho_edge: [ 0.0, 111.0, 126.5, 111.0, 42.25, 42.25 ], +z_origin: [ -40.0, 0.0, 0.0, 40.0, -142.0 ], noise_rate: 10000.0, // Hz } - - { name: "PMT", index: "r3600", @@ -980,7 +498,7 @@ valid_end: [0,0], construction: "toroidal", dynode_material: "stainless_steel", -glass_material: "glass", +glass_material: "hamamatsu_borosilicate_glass", pmt_vacuum_material: "pmt_vacuum", photocathode_surface: "photocathode_R3600", photocathode_MINrho: 230.0, From f40ef74f5032990f769c35f3effb8de19b072e45 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Tue, 15 Apr 2025 19:00:16 +0100 Subject: [PATCH 15/52] Added encapsulations --- src/geo/src/pmt/PMTFactoryBase.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/geo/src/pmt/PMTFactoryBase.cc b/src/geo/src/pmt/PMTFactoryBase.cc index b828fb0c..b79f8c34 100644 --- a/src/geo/src/pmt/PMTFactoryBase.cc +++ b/src/geo/src/pmt/PMTFactoryBase.cc @@ -360,7 +360,7 @@ G4VPhysicalVolume *PMTFactoryBase::ConstructPMTs( } // end loop over id - // finally pass the efficiency table to GLGS4PMTOpticalModel + // finally pass the efficiency table to GLG4PMTOpticalModel const G4String modname(volume_name + "_optical_model"); // In case the main pmt volume doesn't correspond to the fastsim region From 45399c765fc6373aab2bfeb2f35e79dad7ecd97f Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Wed, 16 Apr 2025 20:33:46 +0100 Subject: [PATCH 16/52] clang formatting for pull request --- src/geo/CMakeLists.txt | 104 +-- .../RAT/EncapsulatedPMTConstruction.hh | 54 +- .../src/pmt/EncapsulatedPMTConstruction.cc | 822 ++++++++---------- src/geo/src/pmt/PMTConstruction.cc | 2 +- src/geo/src/pmt/PMTFactoryBase.cc | 12 +- 5 files changed, 425 insertions(+), 569 deletions(-) diff --git a/src/geo/CMakeLists.txt b/src/geo/CMakeLists.txt index f2c7ae07..5822c088 100644 --- a/src/geo/CMakeLists.txt +++ b/src/geo/CMakeLists.txt @@ -1,78 +1,32 @@ -########################################################### -# CMakeLists for geo module +########################################################## # +#CMakeLists for geo module -add_library(geo OBJECT - src/BWVetGenericChamber.cc - src/BWVetGenericChamberHit.cc - src/ConeWaveguideConstruction.cc - src/ConeWaveguideFactory.cc - src/DetectorConstruction.cc - src/DetectorFactory.cc - src/GLG4BoxSD.cc - src/GLG4PMTSD.cc - src/GLG4TestSolid.cc - src/GLG4TorusStack.cc - src/GeoBoxFactory.cc - src/GeoBubbleFactory.cc - src/GeoBuilder.cc - src/GeoCalibrationStickFactory.cc - src/GeoCherenkovSourceFactory.cc - src/GeoConvexLensFactory.cc - src/GeoFiberSensitiveDetector.cc - src/GeoFiberSensitiveDetectorHit.cc - src/GeoCutTubeFactory.cc - src/GeoEosFactory.cc - src/GeoFactory.cc - src/GeoLensFactory.cc - src/GeoPerfBoxFactory.cc - src/GeoPerfSphereFactory.cc - src/GeoPerfTubeFactory.cc - src/GeoPolyArrayFactory.cc - src/GeoPolygonFactory.cc - src/GeoReflectorFactory.cc - src/GeoReflectorWaveguideFactory.cc - src/GeoRevArrayFactory.cc - src/GeoRevolutionChimneyFactory.cc - src/GeoRevolutionFactory.cc - src/GeoSolidArrayFactoryBase.cc - src/GeoNestedSolidArrayFactoryBase.cc - src/GeoNestedTubeArrayFactory.cc - src/GeoNestedTubeConstruction.cc - src/GeoSolidFactory.cc - src/GeoSphereFactory.cc - src/GeoSurfaceFactory.cc - src/GeoTorusFactory.cc - src/GeoTubeArrayFactory.cc - src/GeoTubeFactory.cc - src/GeoTubeIntersectionFactory.cc - src/GeoWaterBoxArrayFactory.cc - src/Materials.cc - src/TubeFacetSolid.cc - src/UnionSolidArray.cc - src/WaterBoxConstruction.cc - src/WLSPFactory.cc - src/WLSPCoverFactory.cc - src/GDMLWriteStructure.cc - src/pmt/CubicPMTConstruction.cc - src/pmt/LAPPDConstruction.cc - src/pmt/PMTArrayFactory.cc - src/pmt/PMTConcentrator.cc - src/pmt/PMTConstruction.cc - src/pmt/PMTCoverageFactory.cc - src/pmt/PMTFactoryBase.cc - src/pmt/PMTInfoParser.cc - src/pmt/RevolutionPMTConstruction.cc - src/pmt/ToroidalPMTConstruction.cc - src/pmt/CylindricalPMTConstruction.cc - src/pmt/EncapsulatedPMTConstruction.cc - ) + add_library(geo OBJECT src / BWVetGenericChamber.cc src / BWVetGenericChamberHit.cc src / + ConeWaveguideConstruction.cc src / ConeWaveguideFactory.cc src / DetectorConstruction.cc src / + DetectorFactory.cc src / GLG4BoxSD.cc src / GLG4PMTSD.cc src / GLG4TestSolid.cc src / + GLG4TorusStack.cc src / GeoBoxFactory.cc src / GeoBubbleFactory.cc src / GeoBuilder.cc src / + GeoCalibrationStickFactory.cc src / GeoCherenkovSourceFactory.cc src / GeoConvexLensFactory.cc src / + GeoFiberSensitiveDetector.cc src / GeoFiberSensitiveDetectorHit.cc src / GeoCutTubeFactory.cc src / + GeoEosFactory.cc src / GeoFactory.cc src / GeoLensFactory.cc src / GeoPerfBoxFactory.cc src / + GeoPerfSphereFactory.cc src / GeoPerfTubeFactory.cc src / GeoPolyArrayFactory.cc src / + GeoPolygonFactory.cc src / GeoReflectorFactory.cc src / GeoReflectorWaveguideFactory.cc src / + GeoRevArrayFactory.cc src / GeoRevolutionChimneyFactory.cc src / GeoRevolutionFactory.cc src / + GeoSolidArrayFactoryBase.cc src / GeoNestedSolidArrayFactoryBase.cc src / + GeoNestedTubeArrayFactory.cc src / GeoNestedTubeConstruction.cc src / GeoSolidFactory.cc src / + GeoSphereFactory.cc src / GeoSurfaceFactory.cc src / GeoTorusFactory.cc src / + GeoTubeArrayFactory.cc src / GeoTubeFactory.cc src / GeoTubeIntersectionFactory.cc src / + GeoWaterBoxArrayFactory.cc src / Materials.cc src / TubeFacetSolid.cc src / UnionSolidArray.cc src / + WaterBoxConstruction.cc src / WLSPFactory.cc src / WLSPCoverFactory.cc src / GDMLWriteStructure.cc src / + pmt / CubicPMTConstruction.cc src / pmt / LAPPDConstruction.cc src / pmt / PMTArrayFactory.cc src / + pmt / PMTConcentrator.cc src / pmt / PMTConstruction.cc src / pmt / PMTCoverageFactory.cc src / pmt / + PMTFactoryBase.cc src / pmt / PMTInfoParser.cc src / pmt / RevolutionPMTConstruction.cc src / pmt / + ToroidalPMTConstruction.cc src / pmt / CylindricalPMTConstruction.cc src / pmt / + EncapsulatedPMTConstruction.cc) -# Set our include directories -target_include_directories(geo SYSTEM PUBLIC - $) -target_include_directories(geo PUBLIC - $ - $) +#Set our include directories + target_include_directories(geo SYSTEM PUBLIC $) + target_include_directories( + geo PUBLIC $ $) -# Copy our headers when installing -file(COPY include/ DESTINATION ${RATPAC_INCLUDE_DIR}) +#Copy our headers when installing + file(COPY include / DESTINATION ${RATPAC_INCLUDE_DIR}) diff --git a/src/geo/include/RAT/EncapsulatedPMTConstruction.hh b/src/geo/include/RAT/EncapsulatedPMTConstruction.hh index c3096d40..a10dc36a 100644 --- a/src/geo/include/RAT/EncapsulatedPMTConstruction.hh +++ b/src/geo/include/RAT/EncapsulatedPMTConstruction.hh @@ -4,12 +4,19 @@ #ifndef __RAT_EncapsulatedPMTConstruction__ #define __RAT_EncapsulatedPMTConstruction__ +#include +#include #include #include #include #include +#include +#include +#include +#include #include #include +#include #include #include #include @@ -17,14 +24,6 @@ #include #include #include - -#include -#include -#include -#include -#include -#include -#include namespace RAT { struct EncapsulatedPMTConstructionParams { @@ -43,15 +42,15 @@ struct EncapsulatedPMTConstructionParams { double minEnvelopeRadius; // Body - std::vector zEdge; // n+1 - std::vector rhoEdge; // n+1 - std::vector zOrigin; // n - double wallThickness; // mm + std::vector zEdge; // n+1 + std::vector rhoEdge; // n+1 + std::vector zOrigin; // n + double wallThickness; // mm - double dynodeRadius; // mm - double dynodeTop; // mm - double photocathode_MINrho; // mm - double photocathode_MAXrho; // mm + double dynodeRadius; // mm + double dynodeTop; // mm + double photocathode_MINrho; // mm + double photocathode_MAXrho; // mm G4Material *exterior; G4Material *glass; @@ -81,31 +80,28 @@ struct EncapsulatedPMTConstructionParams { G4OpticalSurface *silica_bag_surface; G4OpticalSurface *optical_gel_surface; - double efficiencyCorrection; // default to 1.0 for no correction + double efficiencyCorrection; // default to 1.0 for no correction }; // Construction for PMTs based on GLG4TorusStack class EncapsulatedPMTConstruction : public PMTConstruction { -public: + public: EncapsulatedPMTConstruction(DBLinkPtr params, G4LogicalVolume *mother); virtual ~EncapsulatedPMTConstruction() {} virtual G4LogicalVolume *BuildVolume(const std::string &prefix); virtual G4VSolid *BuildSolid(const std::string &prefix); - virtual G4PVPlacement *PlacePMT(G4RotationMatrix *pmtrot, - G4ThreeVector pmtpos, const std::string &name, - G4LogicalVolume *logi_pmt, - G4VPhysicalVolume *mother_phys, - bool booleanSolid, int copyNo); + virtual G4PVPlacement *PlacePMT(G4RotationMatrix *pmtrot, G4ThreeVector pmtpos, const std::string &name, + G4LogicalVolume *logi_pmt, G4VPhysicalVolume *mother_phys, bool booleanSolid, + int copyNo); -protected: + protected: G4VSolid *NewEnvelopeSolid(const std::string &name); G4VSolid *NewEncapsulationSolid(const std::string &name); - G4VSolid *optical_gel_height_subtraction(const std::string &_name); + G4VSolid *optical_gel_height_subtraction(const std::string &_name); G4VSolid *optical_gel_pmt_subtraction(const std::string &_name, GLG4TorusStack *body); - void CalcInnerParams(GLG4TorusStack *body, std::vector &innerZEdge, - std::vector &innerRhoEdge, int &equatorIndex, - double &zLowestDynode); + void CalcInnerParams(GLG4TorusStack *body, std::vector &innerZEdge, std::vector &innerRhoEdge, + int &equatorIndex, double &zLowestDynode); // phyiscal volumes G4PVPlacement *envelope_phys; @@ -135,6 +131,6 @@ protected: EncapsulatedPMTConstructionParams fParams; }; -} // namespace RAT +} // namespace RAT #endif diff --git a/src/geo/src/pmt/EncapsulatedPMTConstruction.cc b/src/geo/src/pmt/EncapsulatedPMTConstruction.cc index 80f7946e..6698f6ea 100644 --- a/src/geo/src/pmt/EncapsulatedPMTConstruction.cc +++ b/src/geo/src/pmt/EncapsulatedPMTConstruction.cc @@ -1,14 +1,19 @@ // This is a modified version of ToroidalPMTConstruction.cc, which encapsulates a toroidal PMT. -// It is intended to be used for BUTTON which uses 96 Hamamatsu r7081pe PMTs that are encapsulated by two acryilic domes. -// Created by Lewis Sexton (Sheffield) and Adam Tarrant (Liverpool) +// It is intended to be used for BUTTON which uses 96 Hamamatsu r7081pe PMTs that are encapsulated by two acryilic +// domes. Created by Lewis Sexton (Sheffield) and Adam Tarrant (Liverpool) #include +#include +#include #include #include +#include #include +#include #include #include +#include #include #include #include @@ -16,17 +21,9 @@ #include #include -#include -#include -#include -#include -#include -#include - namespace RAT { -EncapsulatedPMTConstruction::EncapsulatedPMTConstruction( - DBLinkPtr table, G4LogicalVolume *mother) +EncapsulatedPMTConstruction::EncapsulatedPMTConstruction(DBLinkPtr table, G4LogicalVolume *mother) : PMTConstruction("Encapsulated") { body_phys = 0; inner1_phys = 0; @@ -75,47 +72,29 @@ EncapsulatedPMTConstruction::EncapsulatedPMTConstruction( fParams.photocathode = Materials::optical_surface[pc_surface_name]; std::string mirror_surface_name = table->GetS("mirror_surface"); fParams.mirror = Materials::optical_surface[mirror_surface_name]; - fParams.dynode_surface = - Materials::optical_surface[table->GetS("dynode_surface")]; + fParams.dynode_surface = Materials::optical_surface[table->GetS("dynode_surface")]; // Encapsulation materials - fParams.in_encapsulation_material = - G4Material::GetMaterial(table->GetS("inside_encapsulation_material")); - fParams.front_encapsulation_material = - G4Material::GetMaterial(table->GetS("front_encapsulation_material")); - fParams.rear_encapsulation_material = - G4Material::GetMaterial(table->GetS("rear_encapsulation_material")); - fParams.metal_flange_material = - G4Material::GetMaterial(table->GetS("metal_flange_material")); - fParams.acrylic_flange_material = - G4Material::GetMaterial(table->GetS("acrylic_flange_material")); - fParams.silica_bag_material = - G4Material::GetMaterial(table->GetS("silica_bag_material")); - fParams.cable_material = - G4Material::GetMaterial(table->GetS("cable_material")); - fParams.optical_gel_material = - G4Material::GetMaterial(table->GetS("optical_gel_material")); - - fParams.in_encapsulation_surface = - Materials::optical_surface[table->GetS("inside_encapsulation_material")]; - fParams.front_encapsulation_surface = - Materials::optical_surface[table->GetS("front_encapsulation_material")]; - fParams.rear_encapsulation_surface = - Materials::optical_surface[table->GetS("rear_encapsulation_material")]; - fParams.metal_flange_surface = - Materials::optical_surface[table->GetS("metal_flange_material")]; - fParams.acrylic_flange_surface = - Materials::optical_surface[table->GetS("acrylic_flange_material")]; - fParams.silica_bag_surface = - Materials::optical_surface[table->GetS("silica_bag_material")]; - fParams.cable_surface = - Materials::optical_surface[table->GetS("cable_material")]; - fParams.optical_gel_surface = - Materials::optical_surface[table->GetS("optical_gel_material")]; + fParams.in_encapsulation_material = G4Material::GetMaterial(table->GetS("inside_encapsulation_material")); + fParams.front_encapsulation_material = G4Material::GetMaterial(table->GetS("front_encapsulation_material")); + fParams.rear_encapsulation_material = G4Material::GetMaterial(table->GetS("rear_encapsulation_material")); + fParams.metal_flange_material = G4Material::GetMaterial(table->GetS("metal_flange_material")); + fParams.acrylic_flange_material = G4Material::GetMaterial(table->GetS("acrylic_flange_material")); + fParams.silica_bag_material = G4Material::GetMaterial(table->GetS("silica_bag_material")); + fParams.cable_material = G4Material::GetMaterial(table->GetS("cable_material")); + fParams.optical_gel_material = G4Material::GetMaterial(table->GetS("optical_gel_material")); + + fParams.in_encapsulation_surface = Materials::optical_surface[table->GetS("inside_encapsulation_material")]; + fParams.front_encapsulation_surface = Materials::optical_surface[table->GetS("front_encapsulation_material")]; + fParams.rear_encapsulation_surface = Materials::optical_surface[table->GetS("rear_encapsulation_material")]; + fParams.metal_flange_surface = Materials::optical_surface[table->GetS("metal_flange_material")]; + fParams.acrylic_flange_surface = Materials::optical_surface[table->GetS("acrylic_flange_material")]; + fParams.silica_bag_surface = Materials::optical_surface[table->GetS("silica_bag_material")]; + fParams.cable_surface = Materials::optical_surface[table->GetS("cable_material")]; + fParams.optical_gel_surface = Materials::optical_surface[table->GetS("optical_gel_material")]; if (fParams.photocathode == 0) { - Log::Die("EncapsulatedPMTConstruction error: Photocathode surface \"" + - pc_surface_name + "\" not found"); + Log::Die("EncapsulatedPMTConstruction error: Photocathode surface \"" + pc_surface_name + "\" not found"); } // Set new overall correction if requested (not included in individual) @@ -134,9 +113,10 @@ EncapsulatedPMTConstruction::EncapsulatedPMTConstruction( std::string waveguide_desc = table->GetS("waveguide_desc"); std::string waveguide_table, waveguide_index; if (!DB::ParseTableName(waveguide_desc, waveguide_table, waveguide_index)) { - Log::Die("EncapsulatedPMTConstruction: Waveguide descriptor name is not " - "a valid RATDB table: " + - waveguide_desc); + Log::Die( + "EncapsulatedPMTConstruction: Waveguide descriptor name is not " + "a valid RATDB table: " + + waveguide_desc); } fWaveguideFactory = GlobalFactory::New(waveguide); @@ -147,7 +127,7 @@ EncapsulatedPMTConstruction::EncapsulatedPMTConstruction( } // Build PMT - fParams.useEnvelope = true; // disable the use of envelope volume for now + fParams.useEnvelope = true; // disable the use of envelope volume for now assert(fParams.zEdge.size() == fParams.rhoEdge.size()); assert(fParams.zEdge.size() == fParams.zOrigin.size() + 1); @@ -159,12 +139,11 @@ EncapsulatedPMTConstruction::EncapsulatedPMTConstruction( assert(fParams.mirror); } -G4LogicalVolume * -EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { +G4LogicalVolume *EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { if (log_pmt) { return log_pmt; } - + // Generate PMT solids // envelope cylinder @@ -174,8 +153,7 @@ EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { } // glass body - GLG4TorusStack *body_solid = - (GLG4TorusStack *)BuildSolid(prefix + "_body_solid"); + GLG4TorusStack *body_solid = (GLG4TorusStack *)BuildSolid(prefix + "_body_solid"); // inner vacuum GLG4TorusStack *inner1_solid = new GLG4TorusStack(prefix + "_inner1_solid"); @@ -183,359 +161,321 @@ EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { std::vector innerZEdge, innerRhoEdge; G4double zLowestDynode; int equatorIndex; - CalcInnerParams(body_solid, innerZEdge, innerRhoEdge, equatorIndex, - zLowestDynode); - inner1_solid->SetAllParameters(equatorIndex, &innerZEdge[0], &innerRhoEdge[0], - &fParams.zOrigin[0]); - inner2_solid->SetAllParameters( - fParams.zOrigin.size() - equatorIndex, &innerZEdge[equatorIndex], - &innerRhoEdge[equatorIndex], &fParams.zOrigin[equatorIndex]); + CalcInnerParams(body_solid, innerZEdge, innerRhoEdge, equatorIndex, zLowestDynode); + inner1_solid->SetAllParameters(equatorIndex, &innerZEdge[0], &innerRhoEdge[0], &fParams.zOrigin[0]); + inner2_solid->SetAllParameters(fParams.zOrigin.size() - equatorIndex, &innerZEdge[equatorIndex], + &innerRhoEdge[equatorIndex], &fParams.zOrigin[equatorIndex]); // dynode volume G4double hhDynode = (fParams.dynodeTop - zLowestDynode) / 2.0; - G4Tubs *dynode_solid = - new G4Tubs(prefix + "_dynode_solid", 0.0, - fParams.dynodeRadius, // solid cylinder (FIXME?) - hhDynode, // half height of cylinder - 0., CLHEP::twopi); // cylinder complete in phi + G4Tubs *dynode_solid = new G4Tubs(prefix + "_dynode_solid", 0.0, + fParams.dynodeRadius, // solid cylinder (FIXME?) + hhDynode, // half height of cylinder + 0., CLHEP::twopi); // cylinder complete in phi // tolerance gap between inner1 and inner2, needed to prevent overlap due to // floating point roundoff - G4double hhgap = - 0.5e-3; // half the needed gap between the front and back of the PMT - G4double toleranceGapRadius = - innerRhoEdge[equatorIndex]; // the outer radius of the gap needs to be + G4double hhgap = 0.5e-3; // half the needed gap between the front and back of the PMT + G4double toleranceGapRadius = innerRhoEdge[equatorIndex]; // the outer radius of the gap needs to be // equal to the inner radius of the PMT where // inner1 and inner2 join - G4Tubs *central_gap_solid = - new G4Tubs(prefix + "_central_gap_solid", 0.0, - toleranceGapRadius, // solid cylinder with same radius as PMT - hhgap, // half height of cylinder - 0., CLHEP::twopi); // cylinder complete in phi - + G4Tubs *central_gap_solid = new G4Tubs(prefix + "_central_gap_solid", 0.0, + toleranceGapRadius, // solid cylinder with same radius as PMT + hhgap, // half height of cylinder + 0., CLHEP::twopi); // cylinder complete in phi + // Generate Encapsulation solids - double enc_radius = 20.0; // default radius - double enc_thickness = 0.8; // 8mm encapsulation thickness - + double enc_radius = 20.0; // default radius + double enc_thickness = 0.8; // 8mm encapsulation thickness + G4VSolid *optical_gel_encapsulation_solid = 0; - optical_gel_encapsulation_solid = optical_gel_pmt_subtraction(prefix + "_optical_gel_encapsulation_solid", body_solid); - - G4Sphere *in_encapsulation_solid = - new G4Sphere("in_encapsulation_solid", - (0)*CLHEP::cm, // rmin 20 cm - (enc_radius) * CLHEP::cm, // rmax: 20.8 cm - 0.0, // phi - CLHEP::twopi, 0.0, CLHEP::twopi); // theta - - G4Sphere *front_encapsulation_solid = - new G4Sphere("front_encapsulation_solid", - (enc_radius)*CLHEP::cm, // rmin 20 cm - (enc_radius + enc_thickness) * CLHEP::cm, // rmax: 20.8 cm - 0.5 * CLHEP::pi, CLHEP::twopi, // phi - 0., 0.5 * CLHEP::pi); // theta - - G4Sphere *rear_encapsulation_solid = - new G4Sphere("rear_encapsulation_solid", - (enc_radius)*CLHEP::cm, // rmin 20 cm - (enc_radius + enc_thickness) * CLHEP::cm, // rmax: 20.8 cm - 0.5 * CLHEP::pi, CLHEP::twopi, // phi - 0.5 * CLHEP::pi, 0.5 * CLHEP::pi); // theta + optical_gel_encapsulation_solid = + optical_gel_pmt_subtraction(prefix + "_optical_gel_encapsulation_solid", body_solid); + + G4Sphere *in_encapsulation_solid = new G4Sphere("in_encapsulation_solid", + (0) * CLHEP::cm, // rmin 20 cm + (enc_radius)*CLHEP::cm, // rmax: 20.8 cm + 0.0, // phi + CLHEP::twopi, 0.0, CLHEP::twopi); // theta + + G4Sphere *front_encapsulation_solid = new G4Sphere("front_encapsulation_solid", + (enc_radius)*CLHEP::cm, // rmin 20 cm + (enc_radius + enc_thickness) * CLHEP::cm, // rmax: 20.8 cm + 0.5 * CLHEP::pi, CLHEP::twopi, // phi + 0., 0.5 * CLHEP::pi); // theta + + G4Sphere *rear_encapsulation_solid = new G4Sphere("rear_encapsulation_solid", + (enc_radius)*CLHEP::cm, // rmin 20 cm + (enc_radius + enc_thickness) * CLHEP::cm, // rmax: 20.8 cm + 0.5 * CLHEP::pi, CLHEP::twopi, // phi + 0.5 * CLHEP::pi, 0.5 * CLHEP::pi); // theta G4Tubs *front_metal_flange_solid = new G4Tubs("front_metal_flange_solid", - 21.0 * CLHEP::cm, // rmin - 25.3 * CLHEP::cm, // rmax - 0.4 * CLHEP::cm, // size z - 0, CLHEP::twopi); // phi - + 21.0 * CLHEP::cm, // rmin + 25.3 * CLHEP::cm, // rmax + 0.4 * CLHEP::cm, // size z + 0, CLHEP::twopi); // phi + G4Tubs *rear_metal_flange_solid = new G4Tubs("rear_metal_flange_solid", - 21.0 * CLHEP::cm, // rmin - 25.3 * CLHEP::cm, // rmax - 0.4 * CLHEP::cm, // size z - 0, CLHEP::twopi); // phi - + 21.0 * CLHEP::cm, // rmin + 25.3 * CLHEP::cm, // rmax + 0.4 * CLHEP::cm, // size z + 0, CLHEP::twopi); // phi + G4Tubs *acrylic_flange_solid = new G4Tubs("acrylic_flange_solid", - 20.8 * CLHEP::cm, // rmin - 25.3 * CLHEP::cm, // rmax - 0.7 * CLHEP::cm, // size z - 0, CLHEP::twopi); // phi - - G4Box *silica_bag_solid = new G4Box("silica_bag_solid", 18 * CLHEP::mm, 33 * CLHEP::mm, 3 * CLHEP::mm); // zhalf - + 20.8 * CLHEP::cm, // rmin + 25.3 * CLHEP::cm, // rmax + 0.7 * CLHEP::cm, // size z + 0, CLHEP::twopi); // phi + + G4Box *silica_bag_solid = new G4Box("silica_bag_solid", 18 * CLHEP::mm, 33 * CLHEP::mm, 3 * CLHEP::mm); // zhalf + G4Tubs *cable_solid = new G4Tubs("cable_solid", - 0 * CLHEP::cm, // rmin - 6.5 * CLHEP::mm, // rmax - 4.5 * CLHEP::cm, // size z - 0, CLHEP::twopi); // phi - + 0 * CLHEP::cm, // rmin + 6.5 * CLHEP::mm, // rmax + 4.5 * CLHEP::cm, // size z + 0, CLHEP::twopi); // phi + // ------------ Logical Volumes ------------- - G4LogicalVolume *envelope_log = 0, *body_log, *inner1_log, *inner2_log, - *dynode_log, *central_gap_log; + G4LogicalVolume *envelope_log = 0, *body_log, *inner1_log, *inner2_log, *dynode_log, *central_gap_log; if (fParams.useEnvelope) { - envelope_log = new G4LogicalVolume(envelope_solid, fParams.exterior, - prefix + "_envelope_log"); + envelope_log = new G4LogicalVolume(envelope_solid, fParams.exterior, prefix + "_envelope_log"); } - + // PMT logical volumes - body_log = - new G4LogicalVolume(body_solid, fParams.glass, prefix + "_body_log"); + body_log = new G4LogicalVolume(body_solid, fParams.glass, prefix + "_body_log"); - inner1_log = - new G4LogicalVolume(inner1_solid, fParams.vacuum, prefix + "_inner1_log"); + inner1_log = new G4LogicalVolume(inner1_solid, fParams.vacuum, prefix + "_inner1_log"); - inner2_log = - new G4LogicalVolume(inner2_solid, fParams.vacuum, prefix + "_inner2_log"); + inner2_log = new G4LogicalVolume(inner2_solid, fParams.vacuum, prefix + "_inner2_log"); - dynode_log = - new G4LogicalVolume(dynode_solid, fParams.dynode, prefix + "_dynode_log"); + dynode_log = new G4LogicalVolume(dynode_solid, fParams.dynode, prefix + "_dynode_log"); - central_gap_log = new G4LogicalVolume(central_gap_solid, fParams.vacuum, - prefix + "_central_gap_log"); + central_gap_log = new G4LogicalVolume(central_gap_solid, fParams.vacuum, prefix + "_central_gap_log"); // Encapsulaiton logical volumes - G4LogicalVolume *optical_gel_encapsulation_log = - new G4LogicalVolume(optical_gel_encapsulation_solid, // G4VSolid - fParams.optical_gel_material, // - "optical_gel_encapsulation_log"); - - G4LogicalVolume *in_encapsulation_log = - new G4LogicalVolume(in_encapsulation_solid, // G4VSolid - fParams.in_encapsulation_material, // G4Material - "in_encapsulation_log"); - - G4LogicalVolume *front_encapsulation_log = - new G4LogicalVolume(front_encapsulation_solid, // G4VSolid - fParams.front_encapsulation_material, // G4Material - "front_encapsulation_log"); - - G4LogicalVolume *rear_encapsulation_log = - new G4LogicalVolume(rear_encapsulation_solid, // G4VSolid - fParams.rear_encapsulation_material, // G4Material - "rear_encapsulation_log"); - + G4LogicalVolume *optical_gel_encapsulation_log = new G4LogicalVolume(optical_gel_encapsulation_solid, // G4VSolid + fParams.optical_gel_material, // + "optical_gel_encapsulation_log"); + + G4LogicalVolume *in_encapsulation_log = new G4LogicalVolume(in_encapsulation_solid, // G4VSolid + fParams.in_encapsulation_material, // G4Material + "in_encapsulation_log"); + + G4LogicalVolume *front_encapsulation_log = new G4LogicalVolume(front_encapsulation_solid, // G4VSolid + fParams.front_encapsulation_material, // G4Material + "front_encapsulation_log"); + + G4LogicalVolume *rear_encapsulation_log = new G4LogicalVolume(rear_encapsulation_solid, // G4VSolid + fParams.rear_encapsulation_material, // G4Material + "rear_encapsulation_log"); + G4LogicalVolume *front_metal_flange_encapsulation_log = - new G4LogicalVolume(front_metal_flange_solid, // G4VSolid - fParams.metal_flange_material, // G4Material + new G4LogicalVolume(front_metal_flange_solid, // G4VSolid + fParams.metal_flange_material, // G4Material "front_metal_flange_encapsulation_log"); G4LogicalVolume *rear_metal_flange_encapsulation_log = - new G4LogicalVolume(rear_metal_flange_solid, // G4VSolid - fParams.metal_flange_material, // G4Material + new G4LogicalVolume(rear_metal_flange_solid, // G4VSolid + fParams.metal_flange_material, // G4Material "rear_metal_flange_encapsulation_log"); G4LogicalVolume *acrylic_flange_encapsulation_log = - new G4LogicalVolume(acrylic_flange_solid, // G4VSolid - fParams.acrylic_flange_material, // G4Material + new G4LogicalVolume(acrylic_flange_solid, // G4VSolid + fParams.acrylic_flange_material, // G4Material "acrylic_flange_encapsulation_log"); - G4LogicalVolume *silica_bag_encapsulation_log = - new G4LogicalVolume(silica_bag_solid, // G4VSolid - fParams.silica_bag_material, // G4Materil - "silica_bag_encapsulation_log"); + G4LogicalVolume *silica_bag_encapsulation_log = new G4LogicalVolume(silica_bag_solid, // G4VSolid + fParams.silica_bag_material, // G4Materil + "silica_bag_encapsulation_log"); - G4LogicalVolume *cable_encapsulation_log = - new G4LogicalVolume(cable_solid, // G4VSolid - fParams.cable_material, // G4Material - "cable_encapsulation_log"); + G4LogicalVolume *cable_encapsulation_log = new G4LogicalVolume(cable_solid, // G4VSolid + fParams.cable_material, // G4Material + "cable_encapsulation_log"); // ------------ Physical Volumes ------------- G4ThreeVector noTranslation(0., 0., 0.); body_phys = 0; // Place inner encapsulation volume within mother, ensure it is first daughter! - in_encapsulation_phys = new G4PVPlacement( - 0, // no rotation - G4ThreeVector(0.0, 0. * CLHEP::cm, - 0.0 * CLHEP::cm), // Bounding envelope already constructed - // to put equator at origin - in_encapsulation_log, // the logical volume - prefix + "in_encapsulation_phys", // a name for this physical volume - envelope_log, // the mother volume - false, // no boolean ops - 0); - - // Place PMT within inner encapsulation volume, ensure it is first daughter of first daughter! - body_phys = new G4PVPlacement( /// This subtracts the pmt from the in encapsulation volume - 0, // no rotation - G4ThreeVector(0.0, 0.0, - 9.8 * CLHEP::cm), // Bounding envelope already constructed to put equator - // at origin - body_log, // the logical volume - prefix + "_body_phys", // a name for this physical volume - in_encapsulation_log, // the mother volume - false, // no boolean ops - 0); // copy number - - // Place rest of the inside components - optical_gel_encapsulation_phys = new G4PVPlacement( - 0, // no rotation - G4ThreeVector(0.0, 0. * CLHEP::cm, - 0.0 * CLHEP::cm), // Bounding envelope already constructed - // to put equator at origin - optical_gel_encapsulation_log, // the logical volume - prefix + "in_encapsulation_phys", // a name for this physical volume - in_encapsulation_log, // the mother volume - false, // no boolean ops - 0); - - acrylic_flange_encapsulaion_phys = new G4PVPlacement( - 0, // no rotation - G4ThreeVector(1.0, 1.0, - 0.8 * CLHEP::cm), // Bounding envelope already constructed - // to put equator at origin - acrylic_flange_encapsulation_log, // the logical volume - prefix + "_encapsulation_phys", // a name for this physical volume - in_encapsulation_log, // the mother volume - false, // no boolean ops - 0); - - silica_bag_encapsulation_phys = new G4PVPlacement( - 0, // no rotation - G4ThreeVector(0.0, 13.5 * CLHEP::cm, - -7.4 * CLHEP::cm), // Bounding envelope already constructed - // to put equator at origin - silica_bag_encapsulation_log, // the logical volume - prefix + "_encapsulation_phys", // a name for this physical volume - in_encapsulation_log, // the mother volume - false, // no boolean ops - 0); - - // PLace outer encapsulation components - front_encapsulation_phys = new G4PVPlacement( - 0, // no rotation + in_encapsulation_phys = new G4PVPlacement(0, // no rotation + G4ThreeVector(0.0, 0. * CLHEP::cm, + 0.0 * CLHEP::cm), // Bounding envelope already constructed + // to put equator at origin + in_encapsulation_log, // the logical volume + prefix + "in_encapsulation_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0); + + // Place PMT within inner encapsulation volume, ensure it is first daughter of first daughter! + body_phys = new G4PVPlacement( /// This subtracts the pmt from the in encapsulation volume + 0, // no rotation G4ThreeVector(0.0, 0.0, - 0.0 * CLHEP::cm), // Bounding envelope already constructed - // to put equator at origin - front_encapsulation_log, // the logical volume - prefix + "_encapsulation_phys", // a name for this physical volume - envelope_log, // the mother volume + 9.8 * CLHEP::cm), // Bounding envelope already constructed to put equator + // at origin + body_log, // the logical volume + prefix + "_body_phys", // a name for this physical volume + in_encapsulation_log, // the mother volume false, // no boolean ops 0); // copy number - - rear_encapsulation_phys = new G4PVPlacement( - 0, // no rotation - G4ThreeVector(0.0, 0.0, - 0.0 * CLHEP::cm), // Bounding envelope already constructed - // to put equator at origin - rear_encapsulation_log, // the logical volume - prefix + "_encapsulation_phys", // a name for this physical volume - envelope_log, // the mother volume - false, // no boolean ops - 0); // copy number - - front_metal_encapsulaion_flange_phys = new G4PVPlacement( - 0, // no rotation - G4ThreeVector(0.0, 0.0, - 2. * CLHEP::cm), // Bounding envelope already constructed - // to put equator at origin - front_metal_flange_encapsulation_log, // the logical volume - prefix + "_encapsulation_phys", // a name for this physical volume - envelope_log, // the mother volume - false, // no boolean ops - 0); // copy number - - rear_metal_encapsulation_flange_phys = new G4PVPlacement( - 0, // no rotation - G4ThreeVector(0.0, 0.0, - -0.2 * CLHEP::cm), // Bounding envelope already constructed - // to put equator at origin - rear_metal_flange_encapsulation_log, // the logical volume - prefix + "_encapsulation_phys", // a name for this physical volume - envelope_log, // the mother volume - false, // no boolean ops - 0); // copy number - - - cable_encapsulation_phys = new G4PVPlacement( - 0, // no rotation - G4ThreeVector(0.0, 0.0, - -15.2 * CLHEP::cm), // Bounding envelope already constructed - // to put equator at origin - cable_encapsulation_log, // the logical volume - prefix + "_encapsulation_phys", // a name for this physical volume - envelope_log, // the mother volume - false, // no boolean ops - 0); + + // Place rest of the inside components + optical_gel_encapsulation_phys = + new G4PVPlacement(0, // no rotation + G4ThreeVector(0.0, 0. * CLHEP::cm, + 0.0 * CLHEP::cm), // Bounding envelope already constructed + // to put equator at origin + optical_gel_encapsulation_log, // the logical volume + prefix + "in_encapsulation_phys", // a name for this physical volume + in_encapsulation_log, // the mother volume + false, // no boolean ops + 0); + + acrylic_flange_encapsulaion_phys = + new G4PVPlacement(0, // no rotation + G4ThreeVector(1.0, 1.0, + 0.8 * CLHEP::cm), // Bounding envelope already constructed + // to put equator at origin + acrylic_flange_encapsulation_log, // the logical volume + prefix + "_encapsulation_phys", // a name for this physical volume + in_encapsulation_log, // the mother volume + false, // no boolean ops + 0); + + silica_bag_encapsulation_phys = + new G4PVPlacement(0, // no rotation + G4ThreeVector(0.0, 13.5 * CLHEP::cm, + -7.4 * CLHEP::cm), // Bounding envelope already constructed + // to put equator at origin + silica_bag_encapsulation_log, // the logical volume + prefix + "_encapsulation_phys", // a name for this physical volume + in_encapsulation_log, // the mother volume + false, // no boolean ops + 0); + + // PLace outer encapsulation components + front_encapsulation_phys = new G4PVPlacement(0, // no rotation + G4ThreeVector(0.0, 0.0, + 0.0 * CLHEP::cm), // Bounding envelope already constructed + // to put equator at origin + front_encapsulation_log, // the logical volume + prefix + "_encapsulation_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0); // copy number + + rear_encapsulation_phys = new G4PVPlacement(0, // no rotation + G4ThreeVector(0.0, 0.0, + 0.0 * CLHEP::cm), // Bounding envelope already constructed + // to put equator at origin + rear_encapsulation_log, // the logical volume + prefix + "_encapsulation_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0); // copy number + + front_metal_encapsulaion_flange_phys = + new G4PVPlacement(0, // no rotation + G4ThreeVector(0.0, 0.0, + 2. * CLHEP::cm), // Bounding envelope already constructed + // to put equator at origin + front_metal_flange_encapsulation_log, // the logical volume + prefix + "_encapsulation_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0); // copy number + + rear_metal_encapsulation_flange_phys = + new G4PVPlacement(0, // no rotation + G4ThreeVector(0.0, 0.0, + -0.2 * CLHEP::cm), // Bounding envelope already constructed + // to put equator at origin + rear_metal_flange_encapsulation_log, // the logical volume + prefix + "_encapsulation_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0); // copy number + + cable_encapsulation_phys = + new G4PVPlacement(0, // no rotation + G4ThreeVector(0.0, 0.0, + -15.2 * CLHEP::cm), // Bounding envelope already constructed + // to put equator at origin + cable_encapsulation_log, // the logical volume + prefix + "_encapsulation_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0); // place inner solids in outer solid (vacuum) - inner1_phys = new G4PVPlacement( - 0, // no rotation - G4ThreeVector(0.0, 0.0, 2. * hhgap), // puts face equator in right place, - // in front of tolerance gap - inner1_log, // the logical volume - prefix + "_inner1_phys", // a name for this physical volume - body_log, // the mother volume - false, // no boolean ops - 0); // copy number - - inner2_phys = new G4PVPlacement( - 0, // no rotation - noTranslation, // puts face equator in right place, behind the tolerance - // gap - inner2_log, // the logical volume - prefix + "_inner2_phys", // a name for this physical volume - body_log, // the mother volume - false, // no boolean ops - 0); // copy number + inner1_phys = new G4PVPlacement(0, // no rotation + G4ThreeVector(0.0, 0.0, 2. * hhgap), // puts face equator in right place, + // in front of tolerance gap + inner1_log, // the logical volume + prefix + "_inner1_phys", // a name for this physical volume + body_log, // the mother volume + false, // no boolean ops + 0); // copy number + + inner2_phys = new G4PVPlacement(0, // no rotation + noTranslation, // puts face equator in right place, behind the tolerance + // gap + inner2_log, // the logical volume + prefix + "_inner2_phys", // a name for this physical volume + body_log, // the mother volume + false, // no boolean ops + 0); // copy number // place gap between inner1 and inner2 - central_gap_phys = new G4PVPlacement( - 0, // no rotation - G4ThreeVector( - 0.0, 0.0, - hhgap), // puts face equator in right place, between inner1 and inner2 - central_gap_log, // the logical volume - prefix + "_central_gap_phys", // a name for this physical volume - body_log, // the mother volume - false, // no boolean ops - 0); // copy number + central_gap_phys = + new G4PVPlacement(0, // no rotation + G4ThreeVector(0.0, 0.0, + hhgap), // puts face equator in right place, between inner1 and inner2 + central_gap_log, // the logical volume + prefix + "_central_gap_phys", // a name for this physical volume + body_log, // the mother volume + false, // no boolean ops + 0); // copy number // place dynode in stem/back - dynode_phys = new G4PVPlacement( - 0, G4ThreeVector(0.0, 0.0, fParams.dynodeTop - hhDynode), - prefix + "_dynode_phys", dynode_log, inner2_phys, false, 0); - + dynode_phys = new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, fParams.dynodeTop - hhDynode), prefix + "_dynode_phys", + dynode_log, inner2_phys, false, 0); // build the optical surface for the dynode straight away since we already // have the logical volume - new G4LogicalSkinSurface(prefix + "_dynode_logsurf", dynode_log, - fParams.dynode_surface); + new G4LogicalSkinSurface(prefix + "_dynode_logsurf", dynode_log, fParams.dynode_surface); // Add the encapsulation surfaces - new G4LogicalSkinSurface( - "in_encapsulation_skin", - in_encapsulation_log, // Logical Volume - fParams.in_encapsulation_surface); // Surface Property - new G4LogicalSkinSurface( - "optical_gel_encapsulation_skin", - optical_gel_encapsulation_log, // Logical Volume - fParams.optical_gel_surface); // Surface Property - new G4LogicalSkinSurface( - "front_encapsulation_skin", - front_encapsulation_log, // Logical Volume - fParams.front_encapsulation_surface); // Surface Property - new G4LogicalSkinSurface( - "rear_encapsulation_skin", - rear_encapsulation_log, // Logical Volume - fParams.rear_encapsulation_surface); // Surface Property - new G4LogicalSkinSurface( - "front_metal_flange_encapsulation_skin", - front_metal_flange_encapsulation_log, /// Logical Volume - fParams.metal_flange_surface); // Surface Property - new G4LogicalSkinSurface( - "rear_metal_flange_encapsulation_skin", - rear_metal_flange_encapsulation_log, /// Logical Volume - fParams.metal_flange_surface); // Surface Property + new G4LogicalSkinSurface("in_encapsulation_skin", + in_encapsulation_log, // Logical Volume + fParams.in_encapsulation_surface); // Surface Property + new G4LogicalSkinSurface("optical_gel_encapsulation_skin", + optical_gel_encapsulation_log, // Logical Volume + fParams.optical_gel_surface); // Surface Property + new G4LogicalSkinSurface("front_encapsulation_skin", + front_encapsulation_log, // Logical Volume + fParams.front_encapsulation_surface); // Surface Property + new G4LogicalSkinSurface("rear_encapsulation_skin", + rear_encapsulation_log, // Logical Volume + fParams.rear_encapsulation_surface); // Surface Property + new G4LogicalSkinSurface("front_metal_flange_encapsulation_skin", + front_metal_flange_encapsulation_log, /// Logical Volume + fParams.metal_flange_surface); // Surface Property + new G4LogicalSkinSurface("rear_metal_flange_encapsulation_skin", + rear_metal_flange_encapsulation_log, /// Logical Volume + fParams.metal_flange_surface); // Surface Property new G4LogicalSkinSurface("acrylic_flange_encapsulation_skin", - acrylic_flange_encapsulation_log, /// Logical Volume - fParams.acrylic_flange_surface); // Surface Property + acrylic_flange_encapsulation_log, /// Logical Volume + fParams.acrylic_flange_surface); // Surface Property new G4LogicalSkinSurface("cable_encapsulation_skin", - cable_encapsulation_log, /// Logical Volume - fParams.cable_surface); // Surface Property + cable_encapsulation_log, /// Logical Volume + fParams.cable_surface); // Surface Property new G4LogicalSkinSurface("silica_bag_encapsulation_skin", - silica_bag_encapsulation_log, /// Logical Volume - fParams.silica_bag_surface); // Surface Property + silica_bag_encapsulation_log, /// Logical Volume + fParams.silica_bag_surface); // Surface Property //--------------Exterior Optical Surface----------------- // If we're using an envelope, body_phys has been created and we can therefore @@ -543,24 +483,19 @@ EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { // physical volume has been placed if (fParams.useEnvelope) { // build the mirrored surface - new G4LogicalBorderSurface(prefix + "_mirror_logsurf1", inner2_phys, - body_phys, fParams.mirror); - new G4LogicalBorderSurface(prefix + "_mirror_logsurf2", body_phys, - inner2_phys, fParams.mirror); + new G4LogicalBorderSurface(prefix + "_mirror_logsurf1", inner2_phys, body_phys, fParams.mirror); + new G4LogicalBorderSurface(prefix + "_mirror_logsurf2", body_phys, inner2_phys, fParams.mirror); // also include the tolerance gap - new G4LogicalBorderSurface(prefix + "_central_gap_logsurf1", - central_gap_phys, body_phys, fParams.mirror); - new G4LogicalBorderSurface(prefix + "_central_gap_logsurf2", body_phys, - central_gap_phys, fParams.mirror); + new G4LogicalBorderSurface(prefix + "_central_gap_logsurf1", central_gap_phys, body_phys, fParams.mirror); + new G4LogicalBorderSurface(prefix + "_central_gap_logsurf2", body_phys, central_gap_phys, fParams.mirror); // photocathode surface - new G4LogicalBorderSurface(prefix + "_photocathode_logsurf1", inner1_phys, - body_phys, fParams.photocathode); + new G4LogicalBorderSurface(prefix + "_photocathode_logsurf1", inner1_phys, body_phys, fParams.photocathode); - //encapsulation surface - new G4LogicalBorderSurface(prefix + "_backencap_logsurf1", rear_encapsulation_phys, - envelope_phys, fParams.rear_encapsulation_surface); + // encapsulation surface + new G4LogicalBorderSurface(prefix + "_backencap_logsurf1", rear_encapsulation_phys, envelope_phys, + fParams.rear_encapsulation_surface); } // FIXME if fParams.seEnvelope == false this can't be done yet... @@ -572,18 +507,17 @@ EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { G4Region *body_region = new G4Region(prefix + "_GLG4_PMTOpticalRegion"); body_region->AddRootLogicalVolume(body_log); /*GLG4PMTOpticalModel * pmtOpticalModel =*/ - new GLG4PMTOpticalModel( - prefix + "_optical_model", body_region, body_log, fParams.photocathode, - fParams.efficiencyCorrection, fParams.dynodeTop, fParams.dynodeRadius, - 0.0, /*prepusling handled after absorption*/ - fParams.photocathode_MINrho, fParams.photocathode_MAXrho); + new GLG4PMTOpticalModel(prefix + "_optical_model", body_region, body_log, fParams.photocathode, + fParams.efficiencyCorrection, fParams.dynodeTop, fParams.dynodeRadius, + 0.0, /*prepusling handled after absorption*/ + fParams.photocathode_MINrho, fParams.photocathode_MAXrho); // ------------ Vis Attributes ------------- G4VisAttributes *visAtt; if (fParams.simpleVis) { visAtt = new G4VisAttributes(G4Color(0.0, 1.0, 1.0, 0.05)); if (fParams.useEnvelope) { - // envelope_log->SetVisAttributes(visAtt); + // envelope_log->SetVisAttributes(visAtt); } body_log->SetVisAttributes(G4VisAttributes::GetInvisible()); dynode_log->SetVisAttributes(G4VisAttributes::GetInvisible()); @@ -594,21 +528,17 @@ EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { optical_gel_encapsulation_log->SetVisAttributes(G4VisAttributes::GetInvisible()); front_encapsulation_log->SetVisAttributes(G4VisAttributes::GetInvisible()); rear_encapsulation_log->SetVisAttributes(G4VisAttributes::GetInvisible()); - front_metal_flange_encapsulation_log->SetVisAttributes( - G4VisAttributes::GetInvisible()); - rear_metal_flange_encapsulation_log->SetVisAttributes( - G4VisAttributes::GetInvisible()); - acrylic_flange_encapsulation_log->SetVisAttributes( - G4VisAttributes::GetInvisible()); + front_metal_flange_encapsulation_log->SetVisAttributes(G4VisAttributes::GetInvisible()); + rear_metal_flange_encapsulation_log->SetVisAttributes(G4VisAttributes::GetInvisible()); + acrylic_flange_encapsulation_log->SetVisAttributes(G4VisAttributes::GetInvisible()); cable_encapsulation_log->SetVisAttributes(G4VisAttributes::GetInvisible()); - silica_bag_encapsulation_log->SetVisAttributes( - G4VisAttributes::GetInvisible()); + silica_bag_encapsulation_log->SetVisAttributes(G4VisAttributes::GetInvisible()); } else { if (fParams.useEnvelope) { envelope_log->SetVisAttributes(G4VisAttributes::GetInvisible()); - //visAtt = new G4VisAttributes(G4Color(0.0, 1.0, 0.0, 1.0)); - //envelope_log->SetVisAttributes(visAtt); + // visAtt = new G4VisAttributes(G4Color(0.0, 1.0, 0.0, 1.0)); + // envelope_log->SetVisAttributes(visAtt); } // PMT glass visAtt = new G4VisAttributes(G4Color(0.0, 1.0, 1.0, 0.05)); @@ -643,22 +573,20 @@ EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { cable_encapsulation_log->SetVisAttributes(visAtt); } - log_pmt = envelope_log;//body_log; + log_pmt = envelope_log; // body_log; // if using envelope place waveguide now if (fParams.useEnvelope && fWaveguideFactory) { fWaveguideFactory->SetPMTBodySolid(body_solid); - G4LogicalVolume *log_wg = fWaveguideFactory->Construct( - prefix + "_waveguide_log", log_pmt, fParams.simpleVis); + G4LogicalVolume *log_wg = fWaveguideFactory->Construct(prefix + "_waveguide_log", log_pmt, fParams.simpleVis); G4ThreeVector offsetWg = fWaveguideFactory->GetPlacementOffset(); - new G4PVPlacement(0, // no rotation + new G4PVPlacement(0, // no rotation offsetWg, - log_wg, // the logical volume - prefix + - "_waveguide_phys", // a name for this physical volume - envelope_log, // the mother volume - false, // no boolean ops - 0); // copy number + log_wg, // the logical volume + prefix + "_waveguide_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0); // copy number } return log_pmt; @@ -666,103 +594,80 @@ EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { G4VSolid *EncapsulatedPMTConstruction::BuildSolid(const std::string &_name) { GLG4TorusStack *body = new GLG4TorusStack(_name); - body->SetAllParameters(fParams.zOrigin.size(), &fParams.zEdge[0], - &fParams.rhoEdge[0], &fParams.zOrigin[0]); + body->SetAllParameters(fParams.zOrigin.size(), &fParams.zEdge[0], &fParams.rhoEdge[0], &fParams.zOrigin[0]); return body; } -G4PVPlacement *EncapsulatedPMTConstruction::PlacePMT( - G4RotationMatrix *pmtrot, G4ThreeVector pmtpos, const std::string &_name, - G4LogicalVolume *logi_pmt, G4VPhysicalVolume *mother_phys, - bool booleanSolid, int copyNo) { +G4PVPlacement *EncapsulatedPMTConstruction::PlacePMT(G4RotationMatrix *pmtrot, G4ThreeVector pmtpos, + const std::string &_name, G4LogicalVolume *logi_pmt, + G4VPhysicalVolume *mother_phys, bool booleanSolid, int copyNo) { if (fParams.useEnvelope) { - return new G4PVPlacement(pmtrot, pmtpos, _name, logi_pmt, mother_phys, - booleanSolid, copyNo); + return new G4PVPlacement(pmtrot, pmtpos, _name, logi_pmt, mother_phys, booleanSolid, copyNo); } else { - encapsulation_phys = new G4PVPlacement(pmtrot, pmtpos, _name, logi_pmt, - mother_phys, booleanSolid, copyNo); + encapsulation_phys = new G4PVPlacement(pmtrot, pmtpos, _name, logi_pmt, mother_phys, booleanSolid, copyNo); - body_phys = new G4PVPlacement(pmtrot, pmtpos, _name, logi_pmt, mother_phys, - booleanSolid, copyNo); + body_phys = new G4PVPlacement(pmtrot, pmtpos, _name, logi_pmt, mother_phys, booleanSolid, copyNo); // build the mirrored surface - new G4LogicalBorderSurface(_name + "_mirror_logsurf1", inner2_phys, - body_phys, fParams.mirror); - new G4LogicalBorderSurface(_name + "_mirror_logsurf2", body_phys, - inner2_phys, fParams.mirror); + new G4LogicalBorderSurface(_name + "_mirror_logsurf1", inner2_phys, body_phys, fParams.mirror); + new G4LogicalBorderSurface(_name + "_mirror_logsurf2", body_phys, inner2_phys, fParams.mirror); // also include the tolerance gap - new G4LogicalBorderSurface(_name + "_central_gap_logsurf1", - central_gap_phys, body_phys, fParams.mirror); - new G4LogicalBorderSurface(_name + "_central_gap_logsurf2", body_phys, - central_gap_phys, fParams.mirror); + new G4LogicalBorderSurface(_name + "_central_gap_logsurf1", central_gap_phys, body_phys, fParams.mirror); + new G4LogicalBorderSurface(_name + "_central_gap_logsurf2", body_phys, central_gap_phys, fParams.mirror); // photocathode surface - new G4LogicalBorderSurface(_name + "_photocathode_logsurf1", inner1_phys, - body_phys, fParams.photocathode); + new G4LogicalBorderSurface(_name + "_photocathode_logsurf1", inner1_phys, body_phys, fParams.photocathode); // if not using envelope place waveguide now if (fWaveguideFactory) { - G4LogicalVolume *log_wg = fWaveguideFactory->Construct( - _name + "_waveguide_log", logi_pmt, fParams.simpleVis); + G4LogicalVolume *log_wg = fWaveguideFactory->Construct(_name + "_waveguide_log", logi_pmt, fParams.simpleVis); // pmtrot is a passive rotation, but we need an active one to put offsetWg // into coordinates of mother G4ThreeVector offsetWg = fWaveguideFactory->GetPlacementOffset(); G4ThreeVector offsetWg_rot = pmtrot->inverse()(offsetWg); G4ThreeVector waveguidepos = pmtpos + offsetWg_rot; new G4PVPlacement(pmtrot, waveguidepos, - _name + "_waveguide", // a name for this physical volume - log_wg, // the logical volume - mother_phys, // the mother volume - false, // no boolean ops - 0); // copy number + _name + "_waveguide", // a name for this physical volume + log_wg, // the logical volume + mother_phys, // the mother volume + false, // no boolean ops + 0); // copy number } return body_phys; } } -G4VSolid * -EncapsulatedPMTConstruction::optical_gel_height_subtraction(const std::string &_name) { - - G4Sphere *optical_gel_1 = - new G4Sphere("optical_gel_1_encapsulation_solid", - 15*CLHEP::cm, - 20.0*CLHEP::cm, - 0.5 * CLHEP::pi, CLHEP::twopi, // phi - 0., 0.5 * CLHEP::pi); - G4Tubs *gel_subtract = - new G4Tubs("gel_sub__solid", 0.0, - 25*CLHEP::cm, // solid cylinder (FIXME?) - 15*CLHEP::cm, // half height of cylinder - 0., CLHEP::twopi); // cylinder complete in phi - - return new G4SubtractionSolid(_name, optical_gel_1, gel_subtract, 0, G4ThreeVector(0.0, 0.0, 0.0*CLHEP::cm)); //8.5 +G4VSolid *EncapsulatedPMTConstruction::optical_gel_height_subtraction(const std::string &_name) { + G4Sphere *optical_gel_1 = new G4Sphere("optical_gel_1_encapsulation_solid", 15 * CLHEP::cm, 20.0 * CLHEP::cm, + 0.5 * CLHEP::pi, CLHEP::twopi, // phi + 0., 0.5 * CLHEP::pi); + G4Tubs *gel_subtract = new G4Tubs("gel_sub__solid", 0.0, + 25 * CLHEP::cm, // solid cylinder (FIXME?) + 15 * CLHEP::cm, // half height of cylinder + 0., CLHEP::twopi); // cylinder complete in phi + + return new G4SubtractionSolid(_name, optical_gel_1, gel_subtract, 0, + G4ThreeVector(0.0, 0.0, 0.0 * CLHEP::cm)); // 8.5 } +G4VSolid *EncapsulatedPMTConstruction::optical_gel_pmt_subtraction(const std::string &_name, GLG4TorusStack *body) { + G4VSolid *optical_gel_2 = 0; + optical_gel_2 = optical_gel_height_subtraction("temp_gel" + _name); -G4VSolid * -EncapsulatedPMTConstruction::optical_gel_pmt_subtraction(const std::string &_name, GLG4TorusStack *body){ - - G4VSolid *optical_gel_2 = 0; - optical_gel_2 = optical_gel_height_subtraction("temp_gel"+ _name); - - - return new G4SubtractionSolid(_name, optical_gel_2, body, 0, G4ThreeVector(0.0, 0.0, 9.8*CLHEP::cm)); //8.5 + return new G4SubtractionSolid(_name, optical_gel_2, body, 0, G4ThreeVector(0.0, 0.0, 9.8 * CLHEP::cm)); // 8.5 } -G4VSolid * -EncapsulatedPMTConstruction::NewEnvelopeSolid(const std::string &_name) { - - G4Sphere *outer_s = new G4Sphere(_name+ "_main", 0. * CLHEP::mm, 25.4*CLHEP::cm, 0.0, CLHEP::twopi, 0.0, CLHEP::twopi); +G4VSolid *EncapsulatedPMTConstruction::NewEnvelopeSolid(const std::string &_name) { + G4Sphere *outer_s = + new G4Sphere(_name + "_main", 0. * CLHEP::mm, 25.4 * CLHEP::cm, 0.0, CLHEP::twopi, 0.0, CLHEP::twopi); return outer_s; } -void EncapsulatedPMTConstruction::CalcInnerParams( - GLG4TorusStack *body, std::vector &innerZEdge, - std::vector &innerRhoEdge, int &equatorIndex, - double &zLowestDynode) { - +void EncapsulatedPMTConstruction::CalcInnerParams(GLG4TorusStack *body, std::vector &innerZEdge, + std::vector &innerRhoEdge, int &equatorIndex, + double &zLowestDynode) { ////// The encapsulation size is hard coded in to insure the correct size for /// BUTTON encapsulation but it could be added here if different pmt sizes /// were wanted! @@ -787,8 +692,7 @@ void EncapsulatedPMTConstruction::CalcInnerParams( innerZEdge[0] = outerZEdge[0] - wall; innerRhoEdge[0] = 0.0; for (int i = 1; i < nEdge; i++) { - norm = - body->SurfaceNormal(G4ThreeVector(0.0, outerRhoEdge[i], outerZEdge[i])); + norm = body->SurfaceNormal(G4ThreeVector(0.0, outerRhoEdge[i], outerZEdge[i])); innerZEdge[i] = outerZEdge[i] - wall * norm.z(); innerRhoEdge[i] = outerRhoEdge[i] - wall * norm.y(); if (innerRhoEdge[i] > dynodeRadius && innerZEdge[i] < zLowestDynode) { @@ -809,14 +713,16 @@ void EncapsulatedPMTConstruction::CalcInnerParams( // sanity check equator index if (equatorIndex < 0) { - Log::Die("EncapsulatedPMTConstruction::CalcInnerParams: Pathological PMT " - "shape with no equator edge"); + Log::Die( + "EncapsulatedPMTConstruction::CalcInnerParams: Pathological PMT " + "shape with no equator edge"); } // sanity check on dynode height if (fParams.dynodeTop > innerZEdge[equatorIndex]) { - Log::Die("EncapsulatedPMTConstruction::CalcInnerParams: Top of PMT dynode " - "cannot be higher than equator."); + Log::Die( + "EncapsulatedPMTConstruction::CalcInnerParams: Top of PMT dynode " + "cannot be higher than equator."); } } -} // namespace RAT +} // namespace RAT diff --git a/src/geo/src/pmt/PMTConstruction.cc b/src/geo/src/pmt/PMTConstruction.cc index cce29d7d..187926a1 100644 --- a/src/geo/src/pmt/PMTConstruction.cc +++ b/src/geo/src/pmt/PMTConstruction.cc @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -13,7 +14,6 @@ #include #include #include -#include #include namespace RAT { diff --git a/src/geo/src/pmt/PMTFactoryBase.cc b/src/geo/src/pmt/PMTFactoryBase.cc index b79f8c34..c491d019 100644 --- a/src/geo/src/pmt/PMTFactoryBase.cc +++ b/src/geo/src/pmt/PMTFactoryBase.cc @@ -363,16 +363,16 @@ G4VPhysicalVolume *PMTFactoryBase::ConstructPMTs( // finally pass the efficiency table to GLG4PMTOpticalModel const G4String modname(volume_name + "_optical_model"); // In case the main pmt volume doesn't correspond to the fastsim region - + // For the encapsulated version, the pmt_body is the daughter of the first daughter G4LogicalVolume *fastsim_log_pmt = log_pmt; G4LogicalVolume *fastsim_log_pmt_dau = 0; if (fastsim_log_pmt->GetFastSimulationManager() == NULL) { - if (construction_type == "encapsulated") { - fastsim_log_pmt_dau = log_pmt->GetDaughter(0)->GetLogicalVolume(); - fastsim_log_pmt = fastsim_log_pmt_dau->GetDaughter(0)->GetLogicalVolume(); // Get the glass region - } - else fastsim_log_pmt = log_pmt->GetDaughter(0)->GetLogicalVolume(); + if (construction_type == "encapsulated") { + fastsim_log_pmt_dau = log_pmt->GetDaughter(0)->GetLogicalVolume(); + fastsim_log_pmt = fastsim_log_pmt_dau->GetDaughter(0)->GetLogicalVolume(); // Get the glass region + } else + fastsim_log_pmt = log_pmt->GetDaughter(0)->GetLogicalVolume(); } for (size_t i = 0; i < fastsim_log_pmt->GetFastSimulationManager()->GetFastSimulationModelList().size(); i++) { From ea25a6f0c756d526624b0cb6c719e4643dac1b30 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Wed, 16 Apr 2025 20:42:50 +0100 Subject: [PATCH 17/52] removed clang-format for cmake file --- src/geo/CMakeLists.txt | 104 +++++++++++++++++++++++++++++------------ 1 file changed, 75 insertions(+), 29 deletions(-) diff --git a/src/geo/CMakeLists.txt b/src/geo/CMakeLists.txt index 5822c088..f2c7ae07 100644 --- a/src/geo/CMakeLists.txt +++ b/src/geo/CMakeLists.txt @@ -1,32 +1,78 @@ -########################################################## # -#CMakeLists for geo module +########################################################### +# CMakeLists for geo module - add_library(geo OBJECT src / BWVetGenericChamber.cc src / BWVetGenericChamberHit.cc src / - ConeWaveguideConstruction.cc src / ConeWaveguideFactory.cc src / DetectorConstruction.cc src / - DetectorFactory.cc src / GLG4BoxSD.cc src / GLG4PMTSD.cc src / GLG4TestSolid.cc src / - GLG4TorusStack.cc src / GeoBoxFactory.cc src / GeoBubbleFactory.cc src / GeoBuilder.cc src / - GeoCalibrationStickFactory.cc src / GeoCherenkovSourceFactory.cc src / GeoConvexLensFactory.cc src / - GeoFiberSensitiveDetector.cc src / GeoFiberSensitiveDetectorHit.cc src / GeoCutTubeFactory.cc src / - GeoEosFactory.cc src / GeoFactory.cc src / GeoLensFactory.cc src / GeoPerfBoxFactory.cc src / - GeoPerfSphereFactory.cc src / GeoPerfTubeFactory.cc src / GeoPolyArrayFactory.cc src / - GeoPolygonFactory.cc src / GeoReflectorFactory.cc src / GeoReflectorWaveguideFactory.cc src / - GeoRevArrayFactory.cc src / GeoRevolutionChimneyFactory.cc src / GeoRevolutionFactory.cc src / - GeoSolidArrayFactoryBase.cc src / GeoNestedSolidArrayFactoryBase.cc src / - GeoNestedTubeArrayFactory.cc src / GeoNestedTubeConstruction.cc src / GeoSolidFactory.cc src / - GeoSphereFactory.cc src / GeoSurfaceFactory.cc src / GeoTorusFactory.cc src / - GeoTubeArrayFactory.cc src / GeoTubeFactory.cc src / GeoTubeIntersectionFactory.cc src / - GeoWaterBoxArrayFactory.cc src / Materials.cc src / TubeFacetSolid.cc src / UnionSolidArray.cc src / - WaterBoxConstruction.cc src / WLSPFactory.cc src / WLSPCoverFactory.cc src / GDMLWriteStructure.cc src / - pmt / CubicPMTConstruction.cc src / pmt / LAPPDConstruction.cc src / pmt / PMTArrayFactory.cc src / - pmt / PMTConcentrator.cc src / pmt / PMTConstruction.cc src / pmt / PMTCoverageFactory.cc src / pmt / - PMTFactoryBase.cc src / pmt / PMTInfoParser.cc src / pmt / RevolutionPMTConstruction.cc src / pmt / - ToroidalPMTConstruction.cc src / pmt / CylindricalPMTConstruction.cc src / pmt / - EncapsulatedPMTConstruction.cc) +add_library(geo OBJECT + src/BWVetGenericChamber.cc + src/BWVetGenericChamberHit.cc + src/ConeWaveguideConstruction.cc + src/ConeWaveguideFactory.cc + src/DetectorConstruction.cc + src/DetectorFactory.cc + src/GLG4BoxSD.cc + src/GLG4PMTSD.cc + src/GLG4TestSolid.cc + src/GLG4TorusStack.cc + src/GeoBoxFactory.cc + src/GeoBubbleFactory.cc + src/GeoBuilder.cc + src/GeoCalibrationStickFactory.cc + src/GeoCherenkovSourceFactory.cc + src/GeoConvexLensFactory.cc + src/GeoFiberSensitiveDetector.cc + src/GeoFiberSensitiveDetectorHit.cc + src/GeoCutTubeFactory.cc + src/GeoEosFactory.cc + src/GeoFactory.cc + src/GeoLensFactory.cc + src/GeoPerfBoxFactory.cc + src/GeoPerfSphereFactory.cc + src/GeoPerfTubeFactory.cc + src/GeoPolyArrayFactory.cc + src/GeoPolygonFactory.cc + src/GeoReflectorFactory.cc + src/GeoReflectorWaveguideFactory.cc + src/GeoRevArrayFactory.cc + src/GeoRevolutionChimneyFactory.cc + src/GeoRevolutionFactory.cc + src/GeoSolidArrayFactoryBase.cc + src/GeoNestedSolidArrayFactoryBase.cc + src/GeoNestedTubeArrayFactory.cc + src/GeoNestedTubeConstruction.cc + src/GeoSolidFactory.cc + src/GeoSphereFactory.cc + src/GeoSurfaceFactory.cc + src/GeoTorusFactory.cc + src/GeoTubeArrayFactory.cc + src/GeoTubeFactory.cc + src/GeoTubeIntersectionFactory.cc + src/GeoWaterBoxArrayFactory.cc + src/Materials.cc + src/TubeFacetSolid.cc + src/UnionSolidArray.cc + src/WaterBoxConstruction.cc + src/WLSPFactory.cc + src/WLSPCoverFactory.cc + src/GDMLWriteStructure.cc + src/pmt/CubicPMTConstruction.cc + src/pmt/LAPPDConstruction.cc + src/pmt/PMTArrayFactory.cc + src/pmt/PMTConcentrator.cc + src/pmt/PMTConstruction.cc + src/pmt/PMTCoverageFactory.cc + src/pmt/PMTFactoryBase.cc + src/pmt/PMTInfoParser.cc + src/pmt/RevolutionPMTConstruction.cc + src/pmt/ToroidalPMTConstruction.cc + src/pmt/CylindricalPMTConstruction.cc + src/pmt/EncapsulatedPMTConstruction.cc + ) -#Set our include directories - target_include_directories(geo SYSTEM PUBLIC $) - target_include_directories( - geo PUBLIC $ $) +# Set our include directories +target_include_directories(geo SYSTEM PUBLIC + $) +target_include_directories(geo PUBLIC + $ + $) -#Copy our headers when installing - file(COPY include / DESTINATION ${RATPAC_INCLUDE_DIR}) +# Copy our headers when installing +file(COPY include/ DESTINATION ${RATPAC_INCLUDE_DIR}) From c9091206f9e3ab61bc24d121335a4dfc18874eba Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Wed, 7 May 2025 12:57:43 +0100 Subject: [PATCH 18/52] New encapsulation methodsimilar to PMTConstruction --- ratdb/ENCAPSULATION.ratdb | 36 + src/geo/CMakeLists.txt | 3 +- .../RAT/EncapsulatedPMTConstruction.hh | 136 ---- .../include/RAT/HemisphereEncapsulation.hh | 102 +++ .../RAT/PMTEncapsulationConstruction.hh | 34 + .../src/pmt/EncapsulatedPMTConstruction.cc | 728 ------------------ src/geo/src/pmt/HemisphereEncapsulation.cc | 483 ++++++++++++ src/geo/src/pmt/PMTConstruction.cc | 3 - .../src/pmt/PMTEncapsulationConstruction.cc | 25 + src/geo/src/pmt/PMTFactoryBase.cc | 69 +- 10 files changed, 739 insertions(+), 880 deletions(-) create mode 100644 ratdb/ENCAPSULATION.ratdb delete mode 100644 src/geo/include/RAT/EncapsulatedPMTConstruction.hh create mode 100644 src/geo/include/RAT/HemisphereEncapsulation.hh create mode 100644 src/geo/include/RAT/PMTEncapsulationConstruction.hh delete mode 100644 src/geo/src/pmt/EncapsulatedPMTConstruction.cc create mode 100644 src/geo/src/pmt/HemisphereEncapsulation.cc create mode 100644 src/geo/src/pmt/PMTEncapsulationConstruction.cc diff --git a/ratdb/ENCAPSULATION.ratdb b/ratdb/ENCAPSULATION.ratdb new file mode 100644 index 00000000..4841c4cb --- /dev/null +++ b/ratdb/ENCAPSULATION.ratdb @@ -0,0 +1,36 @@ +{ +name: + "ENCAPSULATION", index : "BUTTON", + valid_begin : [ 0, 0 ], + valid_end : [ 0, 0 ], + + construction + : "hemisphere", + + envelope_radius : 24.4, // should be large enough to fit all objects (>flange_rmax) + front_encapsulation_material : "nakano_acrylic", + rear_encapsulation_material + : "acrylic_black", + flange_rmax : 24.3, // applies to acrylic and metal flange + encap_radius : 20.0, + encap_thickness : 0.8, + use_metal_flange : 1, + metal_flange_material : "stainless_steel", + metal_flange_dimensions : [ 21.0, 24.3, 0.4 ], // G4Tubs dimensions rmin, rmax, z + inside_encapsulation_material : "air", + use_optical_gel : 1, + optical_gel_material + : "optical_grease", + optical_gel_sub_height : 15.0, // start from a dome full of gel of size encap_radius, e.g. height of gel dome + // left is (encap_radius - optical_gel_sub_height) + pmtposoffset : [ 0.0, 0.0, 9.8 ], + use_silica_bag : 1, + silica_bag_material : "acrylic_white", + silica_bag_dimensions : [ 1.8, 3.3, 0.3 ], // G4Box dimensions x, y, z + silica_bag_position + : [ 0.0, 13.5, -7.4 ], // x, y, z + use_cable : 1, + cable_material : "acrylic_black", + cable_dimensions : [ 0.0, 0.65, 4.5 ], // G4Tubs dimensions rmin, rmax, z + cable_position : [ 0.0, 0.0, -15.2 ], // x, y, z +} diff --git a/src/geo/CMakeLists.txt b/src/geo/CMakeLists.txt index f2c7ae07..c1366ec2 100644 --- a/src/geo/CMakeLists.txt +++ b/src/geo/CMakeLists.txt @@ -64,7 +64,8 @@ add_library(geo OBJECT src/pmt/RevolutionPMTConstruction.cc src/pmt/ToroidalPMTConstruction.cc src/pmt/CylindricalPMTConstruction.cc - src/pmt/EncapsulatedPMTConstruction.cc + src/pmt/PMTEncapsulationConstruction.cc + src/pmt/HemisphereEncapsulation.cc ) # Set our include directories diff --git a/src/geo/include/RAT/EncapsulatedPMTConstruction.hh b/src/geo/include/RAT/EncapsulatedPMTConstruction.hh deleted file mode 100644 index a10dc36a..00000000 --- a/src/geo/include/RAT/EncapsulatedPMTConstruction.hh +++ /dev/null @@ -1,136 +0,0 @@ -// Adam T: A encapsulat// Adam T: A encapsulated pmt based off the Toroidal pmt construction model for -// button (some of the offesets will need adjusted for different pmt this will -// work for the r7081pe model) -#ifndef __RAT_EncapsulatedPMTConstruction__ -#define __RAT_EncapsulatedPMTConstruction__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -namespace RAT { - -struct EncapsulatedPMTConstructionParams { - EncapsulatedPMTConstructionParams() { - efficiencyCorrection = 1.0; - simpleVis = false; - photocathode_MINrho = 0.0; - photocathode_MAXrho = 0.0; - }; - - bool simpleVis; - - // Envelope control - bool useEnvelope; - double faceGap; - double minEnvelopeRadius; - - // Body - std::vector zEdge; // n+1 - std::vector rhoEdge; // n+1 - std::vector zOrigin; // n - double wallThickness; // mm - - double dynodeRadius; // mm - double dynodeTop; // mm - double photocathode_MINrho; // mm - double photocathode_MAXrho; // mm - - G4Material *exterior; - G4Material *glass; - G4Material *vacuum; - G4Material *dynode; - - G4OpticalSurface *photocathode; - G4OpticalSurface *mirror; - G4OpticalSurface *dynode_surface; - - // Encapsulation - G4Material *in_encapsulation_material; - G4Material *front_encapsulation_material; - G4Material *rear_encapsulation_material; - G4Material *metal_flange_material; - G4Material *acrylic_flange_material; - G4Material *silica_bag_material; - G4Material *cable_material; - G4Material *optical_gel_material; - - G4OpticalSurface *in_encapsulation_surface; - G4OpticalSurface *front_encapsulation_surface; - G4OpticalSurface *rear_encapsulation_surface; - G4OpticalSurface *metal_flange_surface; - G4OpticalSurface *acrylic_flange_surface; - G4OpticalSurface *cable_surface; - G4OpticalSurface *silica_bag_surface; - G4OpticalSurface *optical_gel_surface; - - double efficiencyCorrection; // default to 1.0 for no correction -}; - -// Construction for PMTs based on GLG4TorusStack -class EncapsulatedPMTConstruction : public PMTConstruction { - public: - EncapsulatedPMTConstruction(DBLinkPtr params, G4LogicalVolume *mother); - virtual ~EncapsulatedPMTConstruction() {} - - virtual G4LogicalVolume *BuildVolume(const std::string &prefix); - virtual G4VSolid *BuildSolid(const std::string &prefix); - virtual G4PVPlacement *PlacePMT(G4RotationMatrix *pmtrot, G4ThreeVector pmtpos, const std::string &name, - G4LogicalVolume *logi_pmt, G4VPhysicalVolume *mother_phys, bool booleanSolid, - int copyNo); - - protected: - G4VSolid *NewEnvelopeSolid(const std::string &name); - G4VSolid *NewEncapsulationSolid(const std::string &name); - G4VSolid *optical_gel_height_subtraction(const std::string &_name); - G4VSolid *optical_gel_pmt_subtraction(const std::string &_name, GLG4TorusStack *body); - void CalcInnerParams(GLG4TorusStack *body, std::vector &innerZEdge, std::vector &innerRhoEdge, - int &equatorIndex, double &zLowestDynode); - - // phyiscal volumes - G4PVPlacement *envelope_phys; - G4PVPlacement *body_phys; - G4PVPlacement *inner1_phys; - G4PVPlacement *inner2_phys; - G4PVPlacement *central_gap_phys; - G4PVPlacement *dynode_phys; - - ///// Encapsulation - G4PVPlacement *in_encapsulation_phys; - G4PVPlacement *optical_gel_encapsulation_phys; - G4PVPlacement *encapsulation_phys; - G4PVPlacement *front_encapsulation_phys; - G4PVPlacement *rear_encapsulation_phys = 0; - G4PVPlacement *front_metal_encapsulaion_flange_phys; - G4PVPlacement *rear_metal_encapsulation_flange_phys; - G4PVPlacement *acrylic_flange_encapsulaion_phys; - G4PVPlacement *silica_bag_encapsulation_phys; - G4PVPlacement *silica_bag_encapsulation_phys2; - G4PVPlacement *cable_encapsulation_phys; - - G4LogicalVolume *log_pmt; - - WaveguideFactory *fWaveguideFactory; - - EncapsulatedPMTConstructionParams fParams; -}; - -} // namespace RAT - -#endif diff --git a/src/geo/include/RAT/HemisphereEncapsulation.hh b/src/geo/include/RAT/HemisphereEncapsulation.hh new file mode 100644 index 00000000..01f20c7b --- /dev/null +++ b/src/geo/include/RAT/HemisphereEncapsulation.hh @@ -0,0 +1,102 @@ +#ifndef __RAT_HemisphereEncapsulation__ +#define __RAT_HemisphereEncapsulation__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +namespace RAT { + +struct HemisphereEncapsulationParams { + int useMetalFlange; + int useGel; + int useSilicaBag; + int useCable; + + // encapsulation object dimensions + double envelope_radius; + double encap_radius; + double encap_thickness; + double flange_rmax; + double dome_flange_thickness; + double metal_flange_thickness; + double optical_gel_sub_height; + std::vector metal_flange_dimensions; + std::vector silica_bag_dimensions; + std::vector silica_bag_position; + std::vector cable_dimensions; + std::vector cable_position; + + // PMT Body + std::vector zEdge; // n+1 + std::vector rhoEdge; // n+1 + std::vector zOrigin; // n + G4ThreeVector pmtposvec; + std::vector posvec; + + G4Material *exterior_material; + G4Material *inner_encapsulation_material; + G4Material *front_encapsulation_material; + G4Material *rear_encapsulation_material; + G4Material *metal_flange_material; + G4Material *silica_bag_material; + G4Material *cable_material; + G4Material *optical_gel_material; + + G4OpticalSurface *inner_encapsulation_surface; + G4OpticalSurface *front_encapsulation_surface; + G4OpticalSurface *rear_encapsulation_surface; + G4OpticalSurface *metal_flange_surface; + G4OpticalSurface *cable_surface; + G4OpticalSurface *silica_bag_surface; + G4OpticalSurface *optical_gel_surface; +}; + +class HemisphereEncapsulation : public PMTEncapsulationConstruction { + public: + HemisphereEncapsulation(DBLinkPtr encaptable, DBLinkPtr pmttable, G4LogicalVolume *mother); + virtual ~HemisphereEncapsulation() {} + + virtual G4LogicalVolume *BuildVolume(const std::string &prefix); + virtual G4VSolid *BuildSolid(const std::string &prefix); + virtual G4PVPlacement *PlaceEncap(G4RotationMatrix *pmtrot, G4ThreeVector pmtpos, const std::string &name, + G4LogicalVolume *logi_pmt, G4VPhysicalVolume *mother_phys, bool booleanSolid, + int copyNo); + + protected: + G4VSolid *NewEnvelopeSolid(const std::string &name); + G4VSolid *NewEncapsulationSolid(const std::string &name); + G4VSolid *optical_gel_height_subtraction(const std::string &_name); + G4VSolid *optical_gel_pmt_subtraction(const std::string &_name, GLG4TorusStack *body); + + // phyiscal volumes + G4PVPlacement *inner_encapsulation_phys; + G4PVPlacement *optical_gel_encapsulation_phys; + G4PVPlacement *front_encapsulation_phys; + G4PVPlacement *rear_encapsulation_phys; + G4PVPlacement *front_metal_encapsulaion_flange_phys; + G4PVPlacement *rear_metal_encapsulation_flange_phys; + G4PVPlacement *silica_bag_encapsulation_phys; + G4PVPlacement *cable_encapsulation_phys; + + HemisphereEncapsulationParams fParams; +}; + +} // namespace RAT + +#endif diff --git a/src/geo/include/RAT/PMTEncapsulationConstruction.hh b/src/geo/include/RAT/PMTEncapsulationConstruction.hh new file mode 100644 index 00000000..407e96c2 --- /dev/null +++ b/src/geo/include/RAT/PMTEncapsulationConstruction.hh @@ -0,0 +1,34 @@ +#ifndef __RAT_PMTEncapsulationConstruction__ +#define __RAT_PMTEncapsulationConstruction__ + +#include +#include +#include +#include +#include +#include + +namespace RAT { + +class PMTEncapsulationConstruction { + public: + + static PMTEncapsulationConstruction *NewConstruction(DBLinkPtr encaptable, DBLinkPtr pmttable, G4LogicalVolume *mother); + + PMTEncapsulationConstruction(std::string _name) : name(_name) {} + + virtual ~PMTEncapsulationConstruction() {} + + virtual G4VSolid *BuildSolid(const std::string &prefix) = 0; + + virtual G4LogicalVolume *BuildVolume(const std::string &prefix) = 0; + + virtual G4PVPlacement *PlaceEncap(G4RotationMatrix *pmtrot, G4ThreeVector pmtpos, const std::string &name, G4LogicalVolume *logi_pmt, G4VPhysicalVolume *mother_phys, bool booleanSolid, int copyNo) = 0; + + protected: + std::string name; +}; + +} // namespace RAT + +#endif diff --git a/src/geo/src/pmt/EncapsulatedPMTConstruction.cc b/src/geo/src/pmt/EncapsulatedPMTConstruction.cc deleted file mode 100644 index 6698f6ea..00000000 --- a/src/geo/src/pmt/EncapsulatedPMTConstruction.cc +++ /dev/null @@ -1,728 +0,0 @@ -// This is a modified version of ToroidalPMTConstruction.cc, which encapsulates a toroidal PMT. -// It is intended to be used for BUTTON which uses 96 Hamamatsu r7081pe PMTs that are encapsulated by two acryilic -// domes. Created by Lewis Sexton (Sheffield) and Adam Tarrant (Liverpool) - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace RAT { - -EncapsulatedPMTConstruction::EncapsulatedPMTConstruction(DBLinkPtr table, G4LogicalVolume *mother) - : PMTConstruction("Encapsulated") { - body_phys = 0; - inner1_phys = 0; - inner2_phys = 0; - central_gap_phys = 0; - dynode_phys = 0; - encapsulation_phys = 0; - in_encapsulation_phys = 0; - front_encapsulation_phys = 0; - rear_encapsulation_phys = 0; - front_metal_encapsulaion_flange_phys = 0; - rear_metal_encapsulation_flange_phys = 0; - acrylic_flange_encapsulaion_phys = 0; - silica_bag_encapsulation_phys = 0; - cable_encapsulation_phys = 0; - optical_gel_encapsulation_phys = 0; - - log_pmt = 0; - - // Setup PMT parameters - fParams.faceGap = 0.1 * CLHEP::mm; - fParams.zEdge = table->GetDArray("z_edge"); - fParams.rhoEdge = table->GetDArray("rho_edge"); - fParams.zOrigin = table->GetDArray("z_origin"); - fParams.dynodeRadius = table->GetD("dynode_radius"); - fParams.dynodeTop = table->GetD("dynode_top"); - fParams.wallThickness = table->GetD("wall_thickness"); - // MFB - fParams.photocathode_MINrho = 0.0; - try { - fParams.photocathode_MINrho = table->GetD("photocathode_MINrho"); - } catch (DBNotFoundError &e) { - }; - fParams.photocathode_MAXrho = 0.0; - try { - fParams.photocathode_MAXrho = table->GetD("photocathode_MAXrho"); - } catch (DBNotFoundError &e) { - }; - - // PMT Materials - fParams.exterior = mother->GetMaterial(); - fParams.glass = G4Material::GetMaterial(table->GetS("glass_material")); - fParams.dynode = G4Material::GetMaterial(table->GetS("dynode_material")); - fParams.vacuum = G4Material::GetMaterial(table->GetS("pmt_vacuum_material")); - std::string pc_surface_name = table->GetS("photocathode_surface"); - fParams.photocathode = Materials::optical_surface[pc_surface_name]; - std::string mirror_surface_name = table->GetS("mirror_surface"); - fParams.mirror = Materials::optical_surface[mirror_surface_name]; - fParams.dynode_surface = Materials::optical_surface[table->GetS("dynode_surface")]; - - // Encapsulation materials - fParams.in_encapsulation_material = G4Material::GetMaterial(table->GetS("inside_encapsulation_material")); - fParams.front_encapsulation_material = G4Material::GetMaterial(table->GetS("front_encapsulation_material")); - fParams.rear_encapsulation_material = G4Material::GetMaterial(table->GetS("rear_encapsulation_material")); - fParams.metal_flange_material = G4Material::GetMaterial(table->GetS("metal_flange_material")); - fParams.acrylic_flange_material = G4Material::GetMaterial(table->GetS("acrylic_flange_material")); - fParams.silica_bag_material = G4Material::GetMaterial(table->GetS("silica_bag_material")); - fParams.cable_material = G4Material::GetMaterial(table->GetS("cable_material")); - fParams.optical_gel_material = G4Material::GetMaterial(table->GetS("optical_gel_material")); - - fParams.in_encapsulation_surface = Materials::optical_surface[table->GetS("inside_encapsulation_material")]; - fParams.front_encapsulation_surface = Materials::optical_surface[table->GetS("front_encapsulation_material")]; - fParams.rear_encapsulation_surface = Materials::optical_surface[table->GetS("rear_encapsulation_material")]; - fParams.metal_flange_surface = Materials::optical_surface[table->GetS("metal_flange_material")]; - fParams.acrylic_flange_surface = Materials::optical_surface[table->GetS("acrylic_flange_material")]; - fParams.silica_bag_surface = Materials::optical_surface[table->GetS("silica_bag_material")]; - fParams.cable_surface = Materials::optical_surface[table->GetS("cable_material")]; - fParams.optical_gel_surface = Materials::optical_surface[table->GetS("optical_gel_material")]; - - if (fParams.photocathode == 0) { - Log::Die("EncapsulatedPMTConstruction error: Photocathode surface \"" + pc_surface_name + "\" not found"); - } - - // Set new overall correction if requested (not included in individual) - try { - double efficiency_correction = table->GetD("efficiency_correction"); - fParams.efficiencyCorrection = efficiency_correction; - } catch (DBNotFoundError &e) { - } - - // --------------- Start building PMT geometry ------------------ - - // Setup for waveguide - fWaveguideFactory = 0; - try { - std::string waveguide = table->GetS("waveguide"); - std::string waveguide_desc = table->GetS("waveguide_desc"); - std::string waveguide_table, waveguide_index; - if (!DB::ParseTableName(waveguide_desc, waveguide_table, waveguide_index)) { - Log::Die( - "EncapsulatedPMTConstruction: Waveguide descriptor name is not " - "a valid RATDB table: " + - waveguide_desc); - } - - fWaveguideFactory = GlobalFactory::New(waveguide); - fWaveguideFactory->SetTable(waveguide_table, waveguide_index); - fParams.faceGap = fWaveguideFactory->GetZTop(); - fParams.minEnvelopeRadius = fWaveguideFactory->GetRadius(); - } catch (DBNotFoundError &e) { - } - - // Build PMT - fParams.useEnvelope = true; // disable the use of envelope volume for now - - assert(fParams.zEdge.size() == fParams.rhoEdge.size()); - assert(fParams.zEdge.size() == fParams.zOrigin.size() + 1); - assert(fParams.exterior); - assert(fParams.glass); - assert(fParams.vacuum); - assert(fParams.dynode); - assert(fParams.photocathode); - assert(fParams.mirror); -} - -G4LogicalVolume *EncapsulatedPMTConstruction::BuildVolume(const std::string &prefix) { - if (log_pmt) { - return log_pmt; - } - - // Generate PMT solids - - // envelope cylinder - G4VSolid *envelope_solid = 0; - if (fParams.useEnvelope) { - envelope_solid = NewEnvelopeSolid(prefix + "_envelope_solid"); - } - - // glass body - GLG4TorusStack *body_solid = (GLG4TorusStack *)BuildSolid(prefix + "_body_solid"); - - // inner vacuum - GLG4TorusStack *inner1_solid = new GLG4TorusStack(prefix + "_inner1_solid"); - GLG4TorusStack *inner2_solid = new GLG4TorusStack(prefix + "_inner2_solid"); - std::vector innerZEdge, innerRhoEdge; - G4double zLowestDynode; - int equatorIndex; - CalcInnerParams(body_solid, innerZEdge, innerRhoEdge, equatorIndex, zLowestDynode); - inner1_solid->SetAllParameters(equatorIndex, &innerZEdge[0], &innerRhoEdge[0], &fParams.zOrigin[0]); - inner2_solid->SetAllParameters(fParams.zOrigin.size() - equatorIndex, &innerZEdge[equatorIndex], - &innerRhoEdge[equatorIndex], &fParams.zOrigin[equatorIndex]); - - // dynode volume - G4double hhDynode = (fParams.dynodeTop - zLowestDynode) / 2.0; - G4Tubs *dynode_solid = new G4Tubs(prefix + "_dynode_solid", 0.0, - fParams.dynodeRadius, // solid cylinder (FIXME?) - hhDynode, // half height of cylinder - 0., CLHEP::twopi); // cylinder complete in phi - - // tolerance gap between inner1 and inner2, needed to prevent overlap due to - // floating point roundoff - G4double hhgap = 0.5e-3; // half the needed gap between the front and back of the PMT - G4double toleranceGapRadius = innerRhoEdge[equatorIndex]; // the outer radius of the gap needs to be - // equal to the inner radius of the PMT where - // inner1 and inner2 join - - G4Tubs *central_gap_solid = new G4Tubs(prefix + "_central_gap_solid", 0.0, - toleranceGapRadius, // solid cylinder with same radius as PMT - hhgap, // half height of cylinder - 0., CLHEP::twopi); // cylinder complete in phi - - // Generate Encapsulation solids - double enc_radius = 20.0; // default radius - double enc_thickness = 0.8; // 8mm encapsulation thickness - - G4VSolid *optical_gel_encapsulation_solid = 0; - optical_gel_encapsulation_solid = - optical_gel_pmt_subtraction(prefix + "_optical_gel_encapsulation_solid", body_solid); - - G4Sphere *in_encapsulation_solid = new G4Sphere("in_encapsulation_solid", - (0) * CLHEP::cm, // rmin 20 cm - (enc_radius)*CLHEP::cm, // rmax: 20.8 cm - 0.0, // phi - CLHEP::twopi, 0.0, CLHEP::twopi); // theta - - G4Sphere *front_encapsulation_solid = new G4Sphere("front_encapsulation_solid", - (enc_radius)*CLHEP::cm, // rmin 20 cm - (enc_radius + enc_thickness) * CLHEP::cm, // rmax: 20.8 cm - 0.5 * CLHEP::pi, CLHEP::twopi, // phi - 0., 0.5 * CLHEP::pi); // theta - - G4Sphere *rear_encapsulation_solid = new G4Sphere("rear_encapsulation_solid", - (enc_radius)*CLHEP::cm, // rmin 20 cm - (enc_radius + enc_thickness) * CLHEP::cm, // rmax: 20.8 cm - 0.5 * CLHEP::pi, CLHEP::twopi, // phi - 0.5 * CLHEP::pi, 0.5 * CLHEP::pi); // theta - - G4Tubs *front_metal_flange_solid = new G4Tubs("front_metal_flange_solid", - 21.0 * CLHEP::cm, // rmin - 25.3 * CLHEP::cm, // rmax - 0.4 * CLHEP::cm, // size z - 0, CLHEP::twopi); // phi - - G4Tubs *rear_metal_flange_solid = new G4Tubs("rear_metal_flange_solid", - 21.0 * CLHEP::cm, // rmin - 25.3 * CLHEP::cm, // rmax - 0.4 * CLHEP::cm, // size z - 0, CLHEP::twopi); // phi - - G4Tubs *acrylic_flange_solid = new G4Tubs("acrylic_flange_solid", - 20.8 * CLHEP::cm, // rmin - 25.3 * CLHEP::cm, // rmax - 0.7 * CLHEP::cm, // size z - 0, CLHEP::twopi); // phi - - G4Box *silica_bag_solid = new G4Box("silica_bag_solid", 18 * CLHEP::mm, 33 * CLHEP::mm, 3 * CLHEP::mm); // zhalf - - G4Tubs *cable_solid = new G4Tubs("cable_solid", - 0 * CLHEP::cm, // rmin - 6.5 * CLHEP::mm, // rmax - 4.5 * CLHEP::cm, // size z - 0, CLHEP::twopi); // phi - - // ------------ Logical Volumes ------------- - G4LogicalVolume *envelope_log = 0, *body_log, *inner1_log, *inner2_log, *dynode_log, *central_gap_log; - - if (fParams.useEnvelope) { - envelope_log = new G4LogicalVolume(envelope_solid, fParams.exterior, prefix + "_envelope_log"); - } - - // PMT logical volumes - body_log = new G4LogicalVolume(body_solid, fParams.glass, prefix + "_body_log"); - - inner1_log = new G4LogicalVolume(inner1_solid, fParams.vacuum, prefix + "_inner1_log"); - - inner2_log = new G4LogicalVolume(inner2_solid, fParams.vacuum, prefix + "_inner2_log"); - - dynode_log = new G4LogicalVolume(dynode_solid, fParams.dynode, prefix + "_dynode_log"); - - central_gap_log = new G4LogicalVolume(central_gap_solid, fParams.vacuum, prefix + "_central_gap_log"); - - // Encapsulaiton logical volumes - G4LogicalVolume *optical_gel_encapsulation_log = new G4LogicalVolume(optical_gel_encapsulation_solid, // G4VSolid - fParams.optical_gel_material, // - "optical_gel_encapsulation_log"); - - G4LogicalVolume *in_encapsulation_log = new G4LogicalVolume(in_encapsulation_solid, // G4VSolid - fParams.in_encapsulation_material, // G4Material - "in_encapsulation_log"); - - G4LogicalVolume *front_encapsulation_log = new G4LogicalVolume(front_encapsulation_solid, // G4VSolid - fParams.front_encapsulation_material, // G4Material - "front_encapsulation_log"); - - G4LogicalVolume *rear_encapsulation_log = new G4LogicalVolume(rear_encapsulation_solid, // G4VSolid - fParams.rear_encapsulation_material, // G4Material - "rear_encapsulation_log"); - - G4LogicalVolume *front_metal_flange_encapsulation_log = - new G4LogicalVolume(front_metal_flange_solid, // G4VSolid - fParams.metal_flange_material, // G4Material - "front_metal_flange_encapsulation_log"); - - G4LogicalVolume *rear_metal_flange_encapsulation_log = - new G4LogicalVolume(rear_metal_flange_solid, // G4VSolid - fParams.metal_flange_material, // G4Material - "rear_metal_flange_encapsulation_log"); - - G4LogicalVolume *acrylic_flange_encapsulation_log = - new G4LogicalVolume(acrylic_flange_solid, // G4VSolid - fParams.acrylic_flange_material, // G4Material - "acrylic_flange_encapsulation_log"); - - G4LogicalVolume *silica_bag_encapsulation_log = new G4LogicalVolume(silica_bag_solid, // G4VSolid - fParams.silica_bag_material, // G4Materil - "silica_bag_encapsulation_log"); - - G4LogicalVolume *cable_encapsulation_log = new G4LogicalVolume(cable_solid, // G4VSolid - fParams.cable_material, // G4Material - "cable_encapsulation_log"); - - // ------------ Physical Volumes ------------- - G4ThreeVector noTranslation(0., 0., 0.); - body_phys = 0; - - // Place inner encapsulation volume within mother, ensure it is first daughter! - in_encapsulation_phys = new G4PVPlacement(0, // no rotation - G4ThreeVector(0.0, 0. * CLHEP::cm, - 0.0 * CLHEP::cm), // Bounding envelope already constructed - // to put equator at origin - in_encapsulation_log, // the logical volume - prefix + "in_encapsulation_phys", // a name for this physical volume - envelope_log, // the mother volume - false, // no boolean ops - 0); - - // Place PMT within inner encapsulation volume, ensure it is first daughter of first daughter! - body_phys = new G4PVPlacement( /// This subtracts the pmt from the in encapsulation volume - 0, // no rotation - G4ThreeVector(0.0, 0.0, - 9.8 * CLHEP::cm), // Bounding envelope already constructed to put equator - // at origin - body_log, // the logical volume - prefix + "_body_phys", // a name for this physical volume - in_encapsulation_log, // the mother volume - false, // no boolean ops - 0); // copy number - - // Place rest of the inside components - optical_gel_encapsulation_phys = - new G4PVPlacement(0, // no rotation - G4ThreeVector(0.0, 0. * CLHEP::cm, - 0.0 * CLHEP::cm), // Bounding envelope already constructed - // to put equator at origin - optical_gel_encapsulation_log, // the logical volume - prefix + "in_encapsulation_phys", // a name for this physical volume - in_encapsulation_log, // the mother volume - false, // no boolean ops - 0); - - acrylic_flange_encapsulaion_phys = - new G4PVPlacement(0, // no rotation - G4ThreeVector(1.0, 1.0, - 0.8 * CLHEP::cm), // Bounding envelope already constructed - // to put equator at origin - acrylic_flange_encapsulation_log, // the logical volume - prefix + "_encapsulation_phys", // a name for this physical volume - in_encapsulation_log, // the mother volume - false, // no boolean ops - 0); - - silica_bag_encapsulation_phys = - new G4PVPlacement(0, // no rotation - G4ThreeVector(0.0, 13.5 * CLHEP::cm, - -7.4 * CLHEP::cm), // Bounding envelope already constructed - // to put equator at origin - silica_bag_encapsulation_log, // the logical volume - prefix + "_encapsulation_phys", // a name for this physical volume - in_encapsulation_log, // the mother volume - false, // no boolean ops - 0); - - // PLace outer encapsulation components - front_encapsulation_phys = new G4PVPlacement(0, // no rotation - G4ThreeVector(0.0, 0.0, - 0.0 * CLHEP::cm), // Bounding envelope already constructed - // to put equator at origin - front_encapsulation_log, // the logical volume - prefix + "_encapsulation_phys", // a name for this physical volume - envelope_log, // the mother volume - false, // no boolean ops - 0); // copy number - - rear_encapsulation_phys = new G4PVPlacement(0, // no rotation - G4ThreeVector(0.0, 0.0, - 0.0 * CLHEP::cm), // Bounding envelope already constructed - // to put equator at origin - rear_encapsulation_log, // the logical volume - prefix + "_encapsulation_phys", // a name for this physical volume - envelope_log, // the mother volume - false, // no boolean ops - 0); // copy number - - front_metal_encapsulaion_flange_phys = - new G4PVPlacement(0, // no rotation - G4ThreeVector(0.0, 0.0, - 2. * CLHEP::cm), // Bounding envelope already constructed - // to put equator at origin - front_metal_flange_encapsulation_log, // the logical volume - prefix + "_encapsulation_phys", // a name for this physical volume - envelope_log, // the mother volume - false, // no boolean ops - 0); // copy number - - rear_metal_encapsulation_flange_phys = - new G4PVPlacement(0, // no rotation - G4ThreeVector(0.0, 0.0, - -0.2 * CLHEP::cm), // Bounding envelope already constructed - // to put equator at origin - rear_metal_flange_encapsulation_log, // the logical volume - prefix + "_encapsulation_phys", // a name for this physical volume - envelope_log, // the mother volume - false, // no boolean ops - 0); // copy number - - cable_encapsulation_phys = - new G4PVPlacement(0, // no rotation - G4ThreeVector(0.0, 0.0, - -15.2 * CLHEP::cm), // Bounding envelope already constructed - // to put equator at origin - cable_encapsulation_log, // the logical volume - prefix + "_encapsulation_phys", // a name for this physical volume - envelope_log, // the mother volume - false, // no boolean ops - 0); - - // place inner solids in outer solid (vacuum) - inner1_phys = new G4PVPlacement(0, // no rotation - G4ThreeVector(0.0, 0.0, 2. * hhgap), // puts face equator in right place, - // in front of tolerance gap - inner1_log, // the logical volume - prefix + "_inner1_phys", // a name for this physical volume - body_log, // the mother volume - false, // no boolean ops - 0); // copy number - - inner2_phys = new G4PVPlacement(0, // no rotation - noTranslation, // puts face equator in right place, behind the tolerance - // gap - inner2_log, // the logical volume - prefix + "_inner2_phys", // a name for this physical volume - body_log, // the mother volume - false, // no boolean ops - 0); // copy number - - // place gap between inner1 and inner2 - central_gap_phys = - new G4PVPlacement(0, // no rotation - G4ThreeVector(0.0, 0.0, - hhgap), // puts face equator in right place, between inner1 and inner2 - central_gap_log, // the logical volume - prefix + "_central_gap_phys", // a name for this physical volume - body_log, // the mother volume - false, // no boolean ops - 0); // copy number - - // place dynode in stem/back - dynode_phys = new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, fParams.dynodeTop - hhDynode), prefix + "_dynode_phys", - dynode_log, inner2_phys, false, 0); - - // build the optical surface for the dynode straight away since we already - // have the logical volume - new G4LogicalSkinSurface(prefix + "_dynode_logsurf", dynode_log, fParams.dynode_surface); - - // Add the encapsulation surfaces - new G4LogicalSkinSurface("in_encapsulation_skin", - in_encapsulation_log, // Logical Volume - fParams.in_encapsulation_surface); // Surface Property - new G4LogicalSkinSurface("optical_gel_encapsulation_skin", - optical_gel_encapsulation_log, // Logical Volume - fParams.optical_gel_surface); // Surface Property - new G4LogicalSkinSurface("front_encapsulation_skin", - front_encapsulation_log, // Logical Volume - fParams.front_encapsulation_surface); // Surface Property - new G4LogicalSkinSurface("rear_encapsulation_skin", - rear_encapsulation_log, // Logical Volume - fParams.rear_encapsulation_surface); // Surface Property - new G4LogicalSkinSurface("front_metal_flange_encapsulation_skin", - front_metal_flange_encapsulation_log, /// Logical Volume - fParams.metal_flange_surface); // Surface Property - new G4LogicalSkinSurface("rear_metal_flange_encapsulation_skin", - rear_metal_flange_encapsulation_log, /// Logical Volume - fParams.metal_flange_surface); // Surface Property - new G4LogicalSkinSurface("acrylic_flange_encapsulation_skin", - acrylic_flange_encapsulation_log, /// Logical Volume - fParams.acrylic_flange_surface); // Surface Property - new G4LogicalSkinSurface("cable_encapsulation_skin", - cable_encapsulation_log, /// Logical Volume - fParams.cable_surface); // Surface Property - new G4LogicalSkinSurface("silica_bag_encapsulation_skin", - silica_bag_encapsulation_log, /// Logical Volume - fParams.silica_bag_surface); // Surface Property - - //--------------Exterior Optical Surface----------------- - // If we're using an envelope, body_phys has been created and we can therefore - // set the optical surfaces, otherwise this must be done later once the - // physical volume has been placed - if (fParams.useEnvelope) { - // build the mirrored surface - new G4LogicalBorderSurface(prefix + "_mirror_logsurf1", inner2_phys, body_phys, fParams.mirror); - new G4LogicalBorderSurface(prefix + "_mirror_logsurf2", body_phys, inner2_phys, fParams.mirror); - - // also include the tolerance gap - new G4LogicalBorderSurface(prefix + "_central_gap_logsurf1", central_gap_phys, body_phys, fParams.mirror); - new G4LogicalBorderSurface(prefix + "_central_gap_logsurf2", body_phys, central_gap_phys, fParams.mirror); - - // photocathode surface - new G4LogicalBorderSurface(prefix + "_photocathode_logsurf1", inner1_phys, body_phys, fParams.photocathode); - - // encapsulation surface - new G4LogicalBorderSurface(prefix + "_backencap_logsurf1", rear_encapsulation_phys, envelope_phys, - fParams.rear_encapsulation_surface); - } - - // FIXME if fParams.seEnvelope == false this can't be done yet... - // Go ahead and place the cathode optical surface---this can always be done at - // this point - // ------------ FastSimulationModel ------------- - // 28-Jul-2006 WGS: Must define a G4Region for Fast Simulations - // (change from Geant 4.7 to Geant 4.8). - G4Region *body_region = new G4Region(prefix + "_GLG4_PMTOpticalRegion"); - body_region->AddRootLogicalVolume(body_log); - /*GLG4PMTOpticalModel * pmtOpticalModel =*/ - new GLG4PMTOpticalModel(prefix + "_optical_model", body_region, body_log, fParams.photocathode, - fParams.efficiencyCorrection, fParams.dynodeTop, fParams.dynodeRadius, - 0.0, /*prepusling handled after absorption*/ - fParams.photocathode_MINrho, fParams.photocathode_MAXrho); - - // ------------ Vis Attributes ------------- - G4VisAttributes *visAtt; - if (fParams.simpleVis) { - visAtt = new G4VisAttributes(G4Color(0.0, 1.0, 1.0, 0.05)); - if (fParams.useEnvelope) { - // envelope_log->SetVisAttributes(visAtt); - } - body_log->SetVisAttributes(G4VisAttributes::GetInvisible()); - dynode_log->SetVisAttributes(G4VisAttributes::GetInvisible()); - inner1_log->SetVisAttributes(G4VisAttributes::GetInvisible()); - inner2_log->SetVisAttributes(G4VisAttributes::GetInvisible()); - central_gap_log->SetVisAttributes(G4VisAttributes::GetInvisible()); - in_encapsulation_log->SetVisAttributes(G4VisAttributes::GetInvisible()); - optical_gel_encapsulation_log->SetVisAttributes(G4VisAttributes::GetInvisible()); - front_encapsulation_log->SetVisAttributes(G4VisAttributes::GetInvisible()); - rear_encapsulation_log->SetVisAttributes(G4VisAttributes::GetInvisible()); - front_metal_flange_encapsulation_log->SetVisAttributes(G4VisAttributes::GetInvisible()); - rear_metal_flange_encapsulation_log->SetVisAttributes(G4VisAttributes::GetInvisible()); - acrylic_flange_encapsulation_log->SetVisAttributes(G4VisAttributes::GetInvisible()); - cable_encapsulation_log->SetVisAttributes(G4VisAttributes::GetInvisible()); - silica_bag_encapsulation_log->SetVisAttributes(G4VisAttributes::GetInvisible()); - - } else { - if (fParams.useEnvelope) { - envelope_log->SetVisAttributes(G4VisAttributes::GetInvisible()); - // visAtt = new G4VisAttributes(G4Color(0.0, 1.0, 0.0, 1.0)); - // envelope_log->SetVisAttributes(visAtt); - } - // PMT glass - visAtt = new G4VisAttributes(G4Color(0.0, 1.0, 1.0, 0.05)); - body_log->SetVisAttributes(visAtt); - // dynode is medium gray - visAtt = new G4VisAttributes(G4Color(0.5, 0.5, 0.5, 1.0)); - dynode_log->SetVisAttributes(visAtt); - // (surface of) interior vacuum is clear orangish gray on top (PC), - // silvery blue on bottom (mirror) - visAtt = new G4VisAttributes(G4Color(0.7, 0.5, 0.3, 0.27)); - inner1_log->SetVisAttributes(visAtt); - visAtt = new G4VisAttributes(G4Color(0.6, 0.7, 0.8, 0.67)); - inner2_log->SetVisAttributes(visAtt); - // central gap is invisible - central_gap_log->SetVisAttributes(G4VisAttributes::GetInvisible()); - // set encap - visAtt = new G4VisAttributes(G4Color(0.77, 0.97, 1., 0.3)); - in_encapsulation_log->SetVisAttributes(visAtt); - visAtt = new G4VisAttributes(G4Color(0.87, 0.81, 0.11, 0.5)); - optical_gel_encapsulation_log->SetVisAttributes(visAtt); - visAtt = new G4VisAttributes(G4Color(0.44, 0.52, 0.78, 0.5)); - front_encapsulation_log->SetVisAttributes(visAtt); - acrylic_flange_encapsulation_log->SetVisAttributes(visAtt); - visAtt = new G4VisAttributes(G4Color(0., 0.03, 0.14, 1.)); - rear_encapsulation_log->SetVisAttributes(visAtt); - visAtt = new G4VisAttributes(G4Color(0.68, 0.68, 0.68, 1.0)); - front_metal_flange_encapsulation_log->SetVisAttributes(visAtt); - rear_metal_flange_encapsulation_log->SetVisAttributes(visAtt); - visAtt = new G4VisAttributes(G4Color(0.3, 0.1, 0.1, 1.0)); - silica_bag_encapsulation_log->SetVisAttributes(visAtt); - visAtt = new G4VisAttributes(G4Color(1.0, 0.18, 0.8, 1.0)); - cable_encapsulation_log->SetVisAttributes(visAtt); - } - - log_pmt = envelope_log; // body_log; - - // if using envelope place waveguide now - if (fParams.useEnvelope && fWaveguideFactory) { - fWaveguideFactory->SetPMTBodySolid(body_solid); - G4LogicalVolume *log_wg = fWaveguideFactory->Construct(prefix + "_waveguide_log", log_pmt, fParams.simpleVis); - G4ThreeVector offsetWg = fWaveguideFactory->GetPlacementOffset(); - new G4PVPlacement(0, // no rotation - offsetWg, - log_wg, // the logical volume - prefix + "_waveguide_phys", // a name for this physical volume - envelope_log, // the mother volume - false, // no boolean ops - 0); // copy number - } - - return log_pmt; -} - -G4VSolid *EncapsulatedPMTConstruction::BuildSolid(const std::string &_name) { - GLG4TorusStack *body = new GLG4TorusStack(_name); - body->SetAllParameters(fParams.zOrigin.size(), &fParams.zEdge[0], &fParams.rhoEdge[0], &fParams.zOrigin[0]); - return body; -} - -G4PVPlacement *EncapsulatedPMTConstruction::PlacePMT(G4RotationMatrix *pmtrot, G4ThreeVector pmtpos, - const std::string &_name, G4LogicalVolume *logi_pmt, - G4VPhysicalVolume *mother_phys, bool booleanSolid, int copyNo) { - if (fParams.useEnvelope) { - return new G4PVPlacement(pmtrot, pmtpos, _name, logi_pmt, mother_phys, booleanSolid, copyNo); - } else { - encapsulation_phys = new G4PVPlacement(pmtrot, pmtpos, _name, logi_pmt, mother_phys, booleanSolid, copyNo); - - body_phys = new G4PVPlacement(pmtrot, pmtpos, _name, logi_pmt, mother_phys, booleanSolid, copyNo); - - // build the mirrored surface - new G4LogicalBorderSurface(_name + "_mirror_logsurf1", inner2_phys, body_phys, fParams.mirror); - new G4LogicalBorderSurface(_name + "_mirror_logsurf2", body_phys, inner2_phys, fParams.mirror); - - // also include the tolerance gap - new G4LogicalBorderSurface(_name + "_central_gap_logsurf1", central_gap_phys, body_phys, fParams.mirror); - new G4LogicalBorderSurface(_name + "_central_gap_logsurf2", body_phys, central_gap_phys, fParams.mirror); - - // photocathode surface - new G4LogicalBorderSurface(_name + "_photocathode_logsurf1", inner1_phys, body_phys, fParams.photocathode); - - // if not using envelope place waveguide now - if (fWaveguideFactory) { - G4LogicalVolume *log_wg = fWaveguideFactory->Construct(_name + "_waveguide_log", logi_pmt, fParams.simpleVis); - // pmtrot is a passive rotation, but we need an active one to put offsetWg - // into coordinates of mother - G4ThreeVector offsetWg = fWaveguideFactory->GetPlacementOffset(); - G4ThreeVector offsetWg_rot = pmtrot->inverse()(offsetWg); - G4ThreeVector waveguidepos = pmtpos + offsetWg_rot; - new G4PVPlacement(pmtrot, waveguidepos, - _name + "_waveguide", // a name for this physical volume - log_wg, // the logical volume - mother_phys, // the mother volume - false, // no boolean ops - 0); // copy number - } - return body_phys; - } -} - -G4VSolid *EncapsulatedPMTConstruction::optical_gel_height_subtraction(const std::string &_name) { - G4Sphere *optical_gel_1 = new G4Sphere("optical_gel_1_encapsulation_solid", 15 * CLHEP::cm, 20.0 * CLHEP::cm, - 0.5 * CLHEP::pi, CLHEP::twopi, // phi - 0., 0.5 * CLHEP::pi); - G4Tubs *gel_subtract = new G4Tubs("gel_sub__solid", 0.0, - 25 * CLHEP::cm, // solid cylinder (FIXME?) - 15 * CLHEP::cm, // half height of cylinder - 0., CLHEP::twopi); // cylinder complete in phi - - return new G4SubtractionSolid(_name, optical_gel_1, gel_subtract, 0, - G4ThreeVector(0.0, 0.0, 0.0 * CLHEP::cm)); // 8.5 -} - -G4VSolid *EncapsulatedPMTConstruction::optical_gel_pmt_subtraction(const std::string &_name, GLG4TorusStack *body) { - G4VSolid *optical_gel_2 = 0; - optical_gel_2 = optical_gel_height_subtraction("temp_gel" + _name); - - return new G4SubtractionSolid(_name, optical_gel_2, body, 0, G4ThreeVector(0.0, 0.0, 9.8 * CLHEP::cm)); // 8.5 -} - -G4VSolid *EncapsulatedPMTConstruction::NewEnvelopeSolid(const std::string &_name) { - G4Sphere *outer_s = - new G4Sphere(_name + "_main", 0. * CLHEP::mm, 25.4 * CLHEP::cm, 0.0, CLHEP::twopi, 0.0, CLHEP::twopi); - - return outer_s; -} - -void EncapsulatedPMTConstruction::CalcInnerParams(GLG4TorusStack *body, std::vector &innerZEdge, - std::vector &innerRhoEdge, int &equatorIndex, - double &zLowestDynode) { - ////// The encapsulation size is hard coded in to insure the correct size for - /// BUTTON encapsulation but it could be added here if different pmt sizes - /// were wanted! - - // Local references - const G4double wall = fParams.wallThickness; - const G4double dynodeRadius = fParams.dynodeRadius; - const std::vector &outerZEdge = fParams.zEdge; - const std::vector &outerRhoEdge = fParams.rhoEdge; - const int nEdge = fParams.zEdge.size() - 1; - - // set shapes of inner volumes, scan for lowest allowed point of dynode - zLowestDynode = fParams.dynodeTop; - innerZEdge.resize(fParams.zEdge.size()); - innerRhoEdge.resize(fParams.rhoEdge.size()); - - // We will have to calculate the inner dimensions of the PMT. - G4ThreeVector norm; - equatorIndex = -1; - - // calculate inner surface edges, check dynode position, and find equator - innerZEdge[0] = outerZEdge[0] - wall; - innerRhoEdge[0] = 0.0; - for (int i = 1; i < nEdge; i++) { - norm = body->SurfaceNormal(G4ThreeVector(0.0, outerRhoEdge[i], outerZEdge[i])); - innerZEdge[i] = outerZEdge[i] - wall * norm.z(); - innerRhoEdge[i] = outerRhoEdge[i] - wall * norm.y(); - if (innerRhoEdge[i] > dynodeRadius && innerZEdge[i] < zLowestDynode) { - zLowestDynode = innerZEdge[i]; - } - if (outerZEdge[i] == 0.0 || innerZEdge[i] == 0.0) { - equatorIndex = i; - } - } - - innerZEdge[nEdge] = outerZEdge[nEdge] + wall; - innerRhoEdge[nEdge] = outerRhoEdge[nEdge] - wall; - - // one final check on dynode allowed position - if (innerRhoEdge[nEdge] > dynodeRadius && innerZEdge[nEdge] < zLowestDynode) { - zLowestDynode = innerZEdge[nEdge]; - } - - // sanity check equator index - if (equatorIndex < 0) { - Log::Die( - "EncapsulatedPMTConstruction::CalcInnerParams: Pathological PMT " - "shape with no equator edge"); - } - // sanity check on dynode height - if (fParams.dynodeTop > innerZEdge[equatorIndex]) { - Log::Die( - "EncapsulatedPMTConstruction::CalcInnerParams: Top of PMT dynode " - "cannot be higher than equator."); - } -} - -} // namespace RAT diff --git a/src/geo/src/pmt/HemisphereEncapsulation.cc b/src/geo/src/pmt/HemisphereEncapsulation.cc new file mode 100644 index 00000000..ca4e2c92 --- /dev/null +++ b/src/geo/src/pmt/HemisphereEncapsulation.cc @@ -0,0 +1,483 @@ +// This is the encapsulation that is used for BUTTON. +// The 96 Hamamatsu r7081pe PMTs are encapsulated by two acryilic domes that are held together with metal flanges. +// Created by Lewis Sexton (Sheffield) and Adam Tarrant (Liverpool) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace RAT { + +HemisphereEncapsulation::HemisphereEncapsulation(DBLinkPtr encaptable, DBLinkPtr pmttable, G4LogicalVolume *mother) + : PMTEncapsulationConstruction("hemisphere") { + inner_encapsulation_phys = 0; + front_encapsulation_phys = 0; + rear_encapsulation_phys = 0; + + fParams.envelope_radius = 0; // default to 0 + try { + fParams.envelope_radius = encaptable->GetD("envelope_radius"); + } catch (DBNotFoundError &e) { + }; + if (fParams.envelope_radius == 0) { + Log::Die("Hemisphere encapsulation turned on but envelope radius not given!"); + } + + fParams.encap_radius = 0; // default to 0 + try { + fParams.encap_radius = encaptable->GetD("encap_radius"); + } catch (DBNotFoundError &e) { + }; + if (fParams.encap_radius == 0) { + Log::Die("Hemisphere encapsulation turned on but dome radius not given!"); + } + + fParams.encap_thickness = 0; // default to 0 + try { + fParams.encap_thickness = encaptable->GetD("encap_thickness"); + } catch (DBNotFoundError &e) { + }; + if (fParams.encap_thickness == 0) { + Log::Die("Hemisphere encapsulation turned on but dome thickness not given!"); + } + + fParams.flange_rmax = 0; // default to 0 + try { + fParams.flange_rmax = encaptable->GetD("flange_rmax"); + } catch (DBNotFoundError &e) { + }; + if (fParams.flange_rmax == 0) { + Log::Die("Hemisphere encapsulation turned on but flange max radius not given!"); + } + + fParams.useMetalFlange = 0; // default to no silica bag + try { + fParams.useMetalFlange = encaptable->GetI("use_metal_flange"); + } catch (DBNotFoundError &e) { + }; + if (fParams.useMetalFlange == 1) { + front_metal_encapsulaion_flange_phys = 0; + rear_metal_encapsulation_flange_phys = 0; + fParams.metal_flange_material = G4Material::GetMaterial(encaptable->GetS("metal_flange_material")); + fParams.metal_flange_surface = Materials::optical_surface[encaptable->GetS("metal_flange_material")]; + fParams.metal_flange_dimensions = encaptable->GetDArray("metal_flange_dimensions"); + } + + // PMT is only needed if optical gel is used + fParams.useGel = 0; // default to no gel + try { + fParams.useGel = encaptable->GetI("use_optical_gel"); + } catch (DBNotFoundError &e) { + }; + if (fParams.useGel == 1) { + optical_gel_encapsulation_phys = 0; + + // Setup PMT parameters + fParams.zEdge = pmttable->GetDArray("z_edge"); + fParams.rhoEdge = pmttable->GetDArray("rho_edge"); + fParams.zOrigin = pmttable->GetDArray("z_origin"); + // Build PMT shape + assert(fParams.zEdge.size() == fParams.rhoEdge.size()); + assert(fParams.zEdge.size() == fParams.zOrigin.size() + 1); + + assert(fParams.exterior_material); + fParams.optical_gel_material = G4Material::GetMaterial(encaptable->GetS("optical_gel_material")); + fParams.optical_gel_surface = Materials::optical_surface[encaptable->GetS("optical_gel_material")]; + + fParams.optical_gel_sub_height = 0; // default to 0 + try { + fParams.optical_gel_sub_height = encaptable->GetD("optical_gel_sub_height"); + } catch (DBNotFoundError &e) { + }; + if (fParams.optical_gel_sub_height == 0) { + info << "No optical gel subtraction value given, set to 0" << newline; + } + + fParams.pmtposvec.setX(0.0); + fParams.pmtposvec.setY(0.0); + fParams.pmtposvec.setZ(0.0); + try { + fParams.posvec = encaptable->GetDArray("pmtposoffset"); + fParams.pmtposvec.setX(fParams.posvec[0] * CLHEP::cm); + fParams.pmtposvec.setY(fParams.posvec[1] * CLHEP::cm); + fParams.pmtposvec.setZ(fParams.posvec[2] * CLHEP::cm); + } catch (DBNotFoundError &e) { + }; + } + + fParams.useSilicaBag = 0; // default to no silica bag + try { + fParams.useSilicaBag = encaptable->GetI("use_silica_bag"); + } catch (DBNotFoundError &e) { + }; + if (fParams.useSilicaBag == 1) { + silica_bag_encapsulation_phys = 0; + fParams.silica_bag_material = G4Material::GetMaterial(encaptable->GetS("silica_bag_material")); + fParams.silica_bag_surface = Materials::optical_surface[encaptable->GetS("silica_bag_material")]; + fParams.silica_bag_dimensions = encaptable->GetDArray("silica_bag_dimensions"); + fParams.silica_bag_position = encaptable->GetDArray("silica_bag_position"); + } + + fParams.useCable = 0; // default to no cable + try { + fParams.useCable = encaptable->GetI("use_cable"); + } catch (DBNotFoundError &e) { + }; + if (fParams.useCable == 1) { + cable_encapsulation_phys = 0; + fParams.cable_material = G4Material::GetMaterial(encaptable->GetS("cable_material")); + fParams.cable_surface = Materials::optical_surface[encaptable->GetS("cable_material")]; + fParams.cable_dimensions = encaptable->GetDArray("cable_dimensions"); + fParams.cable_position = encaptable->GetDArray("cable_position"); + } + + // Encapsulation materials + fParams.exterior_material = mother->GetMaterial(); + fParams.inner_encapsulation_material = G4Material::GetMaterial(encaptable->GetS("inside_encapsulation_material")); + fParams.front_encapsulation_material = G4Material::GetMaterial(encaptable->GetS("front_encapsulation_material")); + fParams.rear_encapsulation_material = G4Material::GetMaterial(encaptable->GetS("rear_encapsulation_material")); + + // Encapsulation surface + fParams.inner_encapsulation_surface = Materials::optical_surface[encaptable->GetS("inside_encapsulation_material")]; + fParams.front_encapsulation_surface = Materials::optical_surface[encaptable->GetS("front_encapsulation_material")]; + fParams.rear_encapsulation_surface = Materials::optical_surface[encaptable->GetS("rear_encapsulation_material")]; +} + +G4LogicalVolume *HemisphereEncapsulation::BuildVolume(const std::string &prefix) { + // ---------- Generate Shapes ---------- + + // Generate Envelope which will house encapsulation and PMT + G4VSolid *envelope_solid = NewEnvelopeSolid("envelope_solid"); + + G4VSolid *front_encapsulation_solid = + new G4Sphere("front_encapsulation_solid", + (fParams.encap_radius) * CLHEP::cm, // rmin + (fParams.encap_radius + fParams.encap_thickness) * CLHEP::cm, // rmax + 0.5 * CLHEP::pi, CLHEP::twopi, // phi + 0.0, 0.5 * CLHEP::pi); // theta + + G4VSolid *rear_encapsulation_solid = + new G4Sphere("rear_encapsulation_solid", + (fParams.encap_radius) * CLHEP::cm, // rmin + (fParams.encap_radius + fParams.encap_thickness) * CLHEP::cm, // rmax + 0.5 * CLHEP::pi, CLHEP::twopi, // phi + 0.5 * CLHEP::pi, 0.5 * CLHEP::pi); // theta + + G4VSolid *dome_flange_solid = + new G4Tubs("dome_flange_solid", + (fParams.encap_radius) * CLHEP::cm, // rmin + (fParams.flange_rmax) * CLHEP::cm, // rmax + (0.5 * fParams.encap_thickness) * CLHEP::cm, // zhalf, thickness is same as dome thickness so 0.8/2.0 + 0.0, CLHEP::twopi); // phi + + front_encapsulation_solid = + new G4UnionSolid("front_encapsulation_solid", front_encapsulation_solid, dome_flange_solid, 0, + G4ThreeVector(0.0, 0.0, (0.5 * fParams.encap_thickness) * CLHEP::cm)); + + rear_encapsulation_solid = new G4UnionSolid("rear_encapsulation_solid", rear_encapsulation_solid, dome_flange_solid, + 0, G4ThreeVector(0.0, 0.0, -(0.5 * fParams.encap_thickness) * CLHEP::cm)); + + G4Tubs *metal_flange_solid = 0; + if (fParams.useMetalFlange == 1) { + metal_flange_solid = new G4Tubs("front_metal_flange_solid", + (fParams.metal_flange_dimensions[0]) * CLHEP::cm, // rmin + (fParams.metal_flange_dimensions[1]) * CLHEP::cm, // rmax + (fParams.metal_flange_dimensions[2]) * CLHEP::cm, // size z half + 0.0, CLHEP::twopi); // phi + } + + G4Sphere *inner_encapsulation_solid = new G4Sphere("inner_encapsulation_solid", + 0.0 * CLHEP::cm, // rmin + (fParams.encap_radius) * CLHEP::cm, // rmax + 0.0, CLHEP::twopi, // phi + 0.0, CLHEP::twopi); // theta + + // If optical gel is used generate pmt shape to substract from gel + // NOTE: THIS WILL ONLY WORK FOR TOROIDAL + G4VSolid *optical_gel_encapsulation_solid = 0; + GLG4TorusStack *body_solid = 0; + + if (fParams.useGel == 1) { + body_solid = (GLG4TorusStack *)BuildSolid(prefix + "_body_solid"); + if (body_solid != NULL) { + info << "pmt shape made" << newline; + } + optical_gel_encapsulation_solid = + optical_gel_pmt_subtraction(prefix + "_optical_gel_encapsulation_solid", body_solid); + } + + G4Box *silica_bag_solid = 0; + if (fParams.useSilicaBag == 1) { + silica_bag_solid = + new G4Box("silica_bag_solid", (fParams.silica_bag_dimensions[0]) * CLHEP::cm, + (fParams.silica_bag_dimensions[1]) * CLHEP::cm, (fParams.silica_bag_dimensions[2]) * CLHEP::cm); + } + + G4Tubs *cable_solid = 0; + if (fParams.useCable == 1) { + cable_solid = new G4Tubs("cable_solid", + (fParams.cable_dimensions[0]) * CLHEP::cm, // rmin + (fParams.cable_dimensions[1]) * CLHEP::cm, // rmax + (fParams.cable_dimensions[2]) * CLHEP::cm, // size z + 0.0, CLHEP::twopi); // phi + } + + // ---------- Logical volumes ---------- + + G4LogicalVolume *envelope_log = 0, *front_encapsulation_log, *rear_encapsulation_log, *metal_flange_encapsulation_log; + G4LogicalVolume *inner_encapsulation_log = 0, *optical_gel_encapsulation_log, *silica_bag_encapsulation_log, + *cable_encapsulation_log; + + envelope_log = new G4LogicalVolume(envelope_solid, fParams.exterior_material, "envelope_log"); + + front_encapsulation_log = + new G4LogicalVolume(front_encapsulation_solid, fParams.front_encapsulation_material, "front_encapsulation_log"); + + rear_encapsulation_log = + new G4LogicalVolume(rear_encapsulation_solid, fParams.rear_encapsulation_material, "rear_encapsulation_log"); + + if (fParams.useMetalFlange == 1) { + metal_flange_encapsulation_log = + new G4LogicalVolume(metal_flange_solid, fParams.metal_flange_material, "metal_flange_encapsulation_log"); + } + + inner_encapsulation_log = + new G4LogicalVolume(inner_encapsulation_solid, fParams.inner_encapsulation_material, "inner_encapsulation_log"); + + if (fParams.useGel == 1) { + optical_gel_encapsulation_log = new G4LogicalVolume(optical_gel_encapsulation_solid, fParams.optical_gel_material, + "optical_gel_encapsulation_log"); + } + + if (fParams.useSilicaBag == 1) { + silica_bag_encapsulation_log = + new G4LogicalVolume(silica_bag_solid, fParams.silica_bag_material, "silica_bag_encapsulation_log"); + } + + if (fParams.useCable == 1) { + cable_encapsulation_log = new G4LogicalVolume(cable_solid, fParams.cable_material, "cable_encapsulation_log"); + } + + // ---------- Physical volumes ---------- + + front_encapsulation_phys = + new G4PVPlacement(0, // rotation + G4ThreeVector(0.0, 0.0, 0.0 * CLHEP::cm), // position + front_encapsulation_log, // the logical volume + prefix + "_front_dome_encapsulation_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0); // copy number + + rear_encapsulation_phys = + new G4PVPlacement(0, // rotation + G4ThreeVector(0.0, 0.0, 0.0 * CLHEP::cm), // position + rear_encapsulation_log, // the logical volume + prefix + "_rear_dome_encapsulation_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0); // copy number + + if (fParams.useMetalFlange == 1) { + double metal_flange_zpos = (fParams.encap_thickness + fParams.metal_flange_dimensions[2]) * CLHEP::cm; + front_metal_encapsulaion_flange_phys = + new G4PVPlacement(0, // rotation + G4ThreeVector(0.0, 0.0, metal_flange_zpos), // position + metal_flange_encapsulation_log, // the logical volume + prefix + "_front_metal_flange_encapsulation_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0); // copy number + + rear_metal_encapsulation_flange_phys = + new G4PVPlacement(0, // rotation + G4ThreeVector(0.0, 0.0, -metal_flange_zpos), // position + metal_flange_encapsulation_log, // the logical volume + prefix + "rear_metal_flange_encapsulation_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0); // copy number + } + + inner_encapsulation_phys = + new G4PVPlacement(0, // rotation + G4ThreeVector(0.0, 0.0, 0.0 * CLHEP::cm), // position + inner_encapsulation_log, // the logical volume + prefix + "_inner_volume_encapsulation_phys", // a name for this physical volume + envelope_log, // the mother volume + false, // no boolean ops + 0); + + if (fParams.useGel == 1) { + optical_gel_encapsulation_phys = + new G4PVPlacement(0, // rotation + G4ThreeVector(0.0, 0.0, 0.0 * CLHEP::cm), // position + optical_gel_encapsulation_log, // the logical volume + prefix + "_gel_encapsulation_phys", // a name for this physical volume + inner_encapsulation_log, // the mother volume + false, // no boolean ops + 0); + } + + if (fParams.useSilicaBag == 1) { + G4ThreeVector silicaposition(fParams.silica_bag_position[0] * CLHEP::cm, fParams.silica_bag_position[1] * CLHEP::cm, + fParams.silica_bag_position[2] * CLHEP::cm); + + silica_bag_encapsulation_phys = + new G4PVPlacement(0, // rotation + silicaposition, // position + silica_bag_encapsulation_log, // the logical volume + prefix + "_silica_encapsulation_phys", // a name for this physical volume + inner_encapsulation_log, // the mother volume + false, // no boolean ops + 0); + } + + if (fParams.useCable == 1) { + G4ThreeVector cableposition(fParams.cable_position[0] * CLHEP::cm, fParams.cable_position[1] * CLHEP::cm, + fParams.cable_position[2] * CLHEP::cm); + + cable_encapsulation_phys = + new G4PVPlacement(0, // rotation + cableposition, // position + cable_encapsulation_log, // the logical volume + prefix + "_cable_encapsulation_phys", // a name for this physical volume + inner_encapsulation_log, // the mother volume + false, // no boolean ops + 0); + } + + // ---------- Skin surfaces ---------- + new G4LogicalSkinSurface("front_encapsulation_skin", + front_encapsulation_log, // Logical Volume + fParams.front_encapsulation_surface); // Surface Property + + new G4LogicalSkinSurface("rear_encapsulation_skin", + rear_encapsulation_log, // Logical Volume + fParams.rear_encapsulation_surface); // Surface Property + + if (fParams.useMetalFlange == 1) { + new G4LogicalSkinSurface("metal_flange_encapsulation_skin", + metal_flange_encapsulation_log, // Logical Volume + fParams.metal_flange_surface); // Surface Property + } + + new G4LogicalSkinSurface("inner_encapsulation_skin", + inner_encapsulation_log, // Logical Volume + fParams.inner_encapsulation_surface); // Surface Property + + if (fParams.useGel == 1) { + new G4LogicalSkinSurface("optical_gel_encapsulation_skin", + optical_gel_encapsulation_log, // Logical Volume + fParams.optical_gel_surface); // Surface Property + } + + if (fParams.useSilicaBag == 1) { + new G4LogicalSkinSurface("silica_bag_encapsulation_skin", + silica_bag_encapsulation_log, // Logical Volume + fParams.silica_bag_surface); // Surface Property + } + + if (fParams.useCable == 1) { + new G4LogicalSkinSurface("cable_encapsulation_skin", + cable_encapsulation_log, // Logical Volume + fParams.cable_surface); // Surface Property + } + + // ---------- Border Surface ---------- + + new G4LogicalBorderSurface(prefix + "_backencap_logsurf1", rear_encapsulation_phys, inner_encapsulation_phys, + fParams.rear_encapsulation_surface); + new G4LogicalBorderSurface(prefix + "_backencap_logsurf2", inner_encapsulation_phys, rear_encapsulation_phys, + fParams.rear_encapsulation_surface); + + // ---------- Visual Attributes ---------- + G4VisAttributes *visAtt; + + envelope_log->SetVisAttributes(G4VisAttributes::GetInvisible()); + + visAtt = new G4VisAttributes(G4Color(0.44, 0.52, 0.78, 0.5)); + front_encapsulation_log->SetVisAttributes(visAtt); + + visAtt = new G4VisAttributes(G4Color(0., 0.03, 0.14, 1.)); + rear_encapsulation_log->SetVisAttributes(visAtt); + + if (fParams.useMetalFlange == 1) { + visAtt = new G4VisAttributes(G4Color(0.68, 0.68, 0.68, 1.0)); + metal_flange_encapsulation_log->SetVisAttributes(visAtt); + } + + visAtt = new G4VisAttributes(G4Color(0.77, 0.97, 1., 0.3)); + inner_encapsulation_log->SetVisAttributes(visAtt); + + if (fParams.useGel == 1) { + visAtt = new G4VisAttributes(G4Color(0.87, 0.81, 0.11, 0.5)); + optical_gel_encapsulation_log->SetVisAttributes(visAtt); + } + + if (fParams.useSilicaBag == 1) { + visAtt = new G4VisAttributes(G4Color(0.3, 0.1, 0.1, 1.0)); + silica_bag_encapsulation_log->SetVisAttributes(visAtt); + } + if (fParams.useCable == 1) { + visAtt = new G4VisAttributes(G4Color(1.0, 0.18, 0.8, 1.0)); + cable_encapsulation_log->SetVisAttributes(visAtt); + } + + return envelope_log; +} + +G4VSolid *HemisphereEncapsulation::BuildSolid(const std::string &_name) { + GLG4TorusStack *body = new GLG4TorusStack(_name); + body->SetAllParameters(fParams.zOrigin.size(), &fParams.zEdge[0], &fParams.rhoEdge[0], &fParams.zOrigin[0]); + return body; +} + +G4VSolid *HemisphereEncapsulation::optical_gel_height_subtraction(const std::string &_name) { + G4Sphere *optical_gel_1 = + new G4Sphere("optical_gel_1_encapsulation_solid", 0.0 * CLHEP::cm, (fParams.encap_radius) * CLHEP::cm, + 0.5 * CLHEP::pi, CLHEP::twopi, 0.0, 0.5 * CLHEP::pi); + + G4Tubs *gel_subtract = new G4Tubs("gel_sub_solid", 0.0, + (fParams.encap_radius) * CLHEP::cm, // solid cylinder + (fParams.optical_gel_sub_height) * CLHEP::cm, // half height of cylinder + 0.0, CLHEP::twopi); // cylinder complete in phi + + return new G4SubtractionSolid(_name, optical_gel_1, gel_subtract, 0, G4ThreeVector(0.0, 0.0, 0.0 * CLHEP::cm)); +} + +G4VSolid *HemisphereEncapsulation::optical_gel_pmt_subtraction(const std::string &_name, GLG4TorusStack *body) { + G4VSolid *optical_gel_2 = optical_gel_height_subtraction("temp_gel" + _name); + + return new G4SubtractionSolid(_name, optical_gel_2, body, 0, fParams.pmtposvec); +} + +G4PVPlacement *HemisphereEncapsulation::PlaceEncap(G4RotationMatrix *pmtrot, G4ThreeVector pmtpos, + const std::string &_name, G4LogicalVolume *logi_pmt, + G4VPhysicalVolume *mother_phys, bool booleanSolid, int copyNo) { + return new G4PVPlacement(pmtrot, pmtpos, _name, logi_pmt, mother_phys, booleanSolid, copyNo); +} + +G4VSolid *HemisphereEncapsulation::NewEnvelopeSolid(const std::string &_name) { + G4Sphere *outer_s = new G4Sphere(_name + "_main", 0. * CLHEP::mm, fParams.envelope_radius * CLHEP::cm, 0.0, + CLHEP::twopi, 0.0, CLHEP::twopi); + return outer_s; +} + +} // namespace RAT diff --git a/src/geo/src/pmt/PMTConstruction.cc b/src/geo/src/pmt/PMTConstruction.cc index 187926a1..09da28cb 100644 --- a/src/geo/src/pmt/PMTConstruction.cc +++ b/src/geo/src/pmt/PMTConstruction.cc @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -30,8 +29,6 @@ PMTConstruction *PMTConstruction::NewConstruction(DBLinkPtr table, G4LogicalVolu return new CubicPMTConstruction(table, mother); } else if (construction == "lappd") { return new LAPPDConstruction(table, mother); - } else if (construction == "encapsulated") { - return new EncapsulatedPMTConstruction(table, mother); } else { Log::Die("PMT construction \'" + construction + "\' does not exist."); } diff --git a/src/geo/src/pmt/PMTEncapsulationConstruction.cc b/src/geo/src/pmt/PMTEncapsulationConstruction.cc new file mode 100644 index 00000000..f927c521 --- /dev/null +++ b/src/geo/src/pmt/PMTEncapsulationConstruction.cc @@ -0,0 +1,25 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace RAT { + +PMTEncapsulationConstruction *PMTEncapsulationConstruction::NewConstruction(DBLinkPtr encaptable, DBLinkPtr pmttable, G4LogicalVolume *mother) { + std::string construction = encaptable->Get("construction"); + if (construction == "hemisphere") { + return new HemisphereEncapsulation(encaptable, pmttable, mother); + } else { + Log::Die("PMT encapsulation \'" + construction + "\' does not exist."); + } + return NULL; +} + +} // namespace RAT diff --git a/src/geo/src/pmt/PMTFactoryBase.cc b/src/geo/src/pmt/PMTFactoryBase.cc index c491d019..43dd1092 100644 --- a/src/geo/src/pmt/PMTFactoryBase.cc +++ b/src/geo/src/pmt/PMTFactoryBase.cc @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -33,7 +34,6 @@ G4VPhysicalVolume *PMTFactoryBase::ConstructPMTs( std::string pmt_model = table->GetS("pmt_model"); DBLinkPtr lpmt = DB::Get()->GetLink("PMT", pmt_model); - std::string construction_type = lpmt->GetS("construction"); // Find mother volume G4LogicalVolume *mother = FindMother(mother_name); @@ -46,8 +46,56 @@ G4VPhysicalVolume *PMTFactoryBase::ConstructPMTs( } G4ThreeVector local_offset = PMTInfoParser::ComputeLocalOffset(mother_name); - PMTConstruction *construction = PMTConstruction::NewConstruction(lpmt, mother); - G4LogicalVolume *log_pmt = construction->BuildVolume(volume_name); + PMTEncapsulationConstruction *encap_construction = 0; + G4LogicalVolume *log_encapenv = 0; + PMTConstruction *construction = 0; + G4LogicalVolume *log_pmt = 0; + G4VPhysicalVolume *phys_mother_encap = 0; + G4PVPlacement *envelope_phys = 0; + G4ThreeVector pmtposition(0.0, 0.0, 0.0); + + int encapsulation = 0; // default to no encapsulation + try { + encapsulation = table->GetI("encapsulation"); + } catch (DBNotFoundError &e) { + }; + if (encapsulation == 1) { + std::string encapsulation_model = table->GetS("encapsulation_model"); // get encapsulation model e.g. BUTTON + DBLinkPtr lencapsulation = DB::Get()->GetLink( + "ENCAPSULATION", encapsulation_model); // find model in ENCAPSULATION.RATDB, need to make this file + + info << "Encapsulation is turned on, using model: " << encapsulation_model << newline; + + encap_construction = PMTEncapsulationConstruction::NewConstruction( + lencapsulation, lpmt, mother); // make encapsulation, need to make/modify file + log_encapenv = encap_construction->BuildVolume(volume_name); + + try { + std::vector posvector = lencapsulation->GetDArray("pmtposoffset"); + pmtposition.setX(posvector[0] * CLHEP::cm); + pmtposition.setY(posvector[1] * CLHEP::cm); + pmtposition.setZ(posvector[2] * CLHEP::cm); + } catch (DBNotFoundError &e) { + }; + + mother = + FindMother("inner_encapsulation_log"); // change mother so that pmt is placed inside encapsulation volume now + if (mother == 0) { + Log::Die("PMTParser: Unable to find mother volume " + mother_name + " for " + volume_name); + } + phys_mother_encap = FindPhysMother("inner_pmts_inner_volume_encapsulation_phys"); + if (phys_mother == 0) { + Log::Die("PMTParser: PMT mother physical volume " + mother_name + " not found"); + } + } + + info << "Creating PMT model" << newline; + construction = PMTConstruction::NewConstruction(lpmt, mother); + log_pmt = construction->BuildVolume(volume_name); + + if (encapsulation == 1) { + envelope_phys = new G4PVPlacement(0, pmtposition, volume_name + "_body_phys", log_pmt, phys_mother_encap, false, 0); + } /* BFields not in the database anywhere and should be looked at */ // FIXME take a look at what's going on with the Bfield stuff - no docs on @@ -356,23 +404,20 @@ G4VPhysicalVolume *PMTFactoryBase::ConstructPMTs( pmtrot->rotateY(angle_y); pmtrot->rotateX(angle_x); - construction->PlacePMT(pmtrot, pmtpos, pmtname, log_pmt, phys_mother, false, id); - + if (encapsulation == 1) { + encap_construction->PlaceEncap(pmtrot, pmtpos, pmtname, log_encapenv, phys_mother, false, id); + } else { + construction->PlacePMT(pmtrot, pmtpos, pmtname, log_pmt, phys_mother, false, id); + } } // end loop over id // finally pass the efficiency table to GLG4PMTOpticalModel const G4String modname(volume_name + "_optical_model"); // In case the main pmt volume doesn't correspond to the fastsim region - // For the encapsulated version, the pmt_body is the daughter of the first daughter G4LogicalVolume *fastsim_log_pmt = log_pmt; - G4LogicalVolume *fastsim_log_pmt_dau = 0; if (fastsim_log_pmt->GetFastSimulationManager() == NULL) { - if (construction_type == "encapsulated") { - fastsim_log_pmt_dau = log_pmt->GetDaughter(0)->GetLogicalVolume(); - fastsim_log_pmt = fastsim_log_pmt_dau->GetDaughter(0)->GetLogicalVolume(); // Get the glass region - } else - fastsim_log_pmt = log_pmt->GetDaughter(0)->GetLogicalVolume(); + fastsim_log_pmt = log_pmt->GetDaughter(0)->GetLogicalVolume(); } for (size_t i = 0; i < fastsim_log_pmt->GetFastSimulationManager()->GetFastSimulationModelList().size(); i++) { From af752a7fb35d3cd838e211784c397b3deacb9457 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Wed, 7 May 2025 13:12:33 +0100 Subject: [PATCH 19/52] New encapsulation method similar to PMTConstruction --- ratdb/ENCAPSULATION.ratdb | 61 +++++++++---------- .../RAT/PMTEncapsulationConstruction.hh | 8 ++- .../src/pmt/PMTEncapsulationConstruction.cc | 3 +- 3 files changed, 35 insertions(+), 37 deletions(-) diff --git a/ratdb/ENCAPSULATION.ratdb b/ratdb/ENCAPSULATION.ratdb index 4841c4cb..d1485602 100644 --- a/ratdb/ENCAPSULATION.ratdb +++ b/ratdb/ENCAPSULATION.ratdb @@ -1,36 +1,31 @@ { -name: - "ENCAPSULATION", index : "BUTTON", - valid_begin : [ 0, 0 ], - valid_end : [ 0, 0 ], +name: "ENCAPSULATION", +index : "BUTTON", +valid_begin : [ 0, 0 ], +valid_end : [ 0, 0 ], - construction - : "hemisphere", - - envelope_radius : 24.4, // should be large enough to fit all objects (>flange_rmax) - front_encapsulation_material : "nakano_acrylic", - rear_encapsulation_material - : "acrylic_black", - flange_rmax : 24.3, // applies to acrylic and metal flange - encap_radius : 20.0, - encap_thickness : 0.8, - use_metal_flange : 1, - metal_flange_material : "stainless_steel", - metal_flange_dimensions : [ 21.0, 24.3, 0.4 ], // G4Tubs dimensions rmin, rmax, z - inside_encapsulation_material : "air", - use_optical_gel : 1, - optical_gel_material - : "optical_grease", - optical_gel_sub_height : 15.0, // start from a dome full of gel of size encap_radius, e.g. height of gel dome - // left is (encap_radius - optical_gel_sub_height) - pmtposoffset : [ 0.0, 0.0, 9.8 ], - use_silica_bag : 1, - silica_bag_material : "acrylic_white", - silica_bag_dimensions : [ 1.8, 3.3, 0.3 ], // G4Box dimensions x, y, z - silica_bag_position - : [ 0.0, 13.5, -7.4 ], // x, y, z - use_cable : 1, - cable_material : "acrylic_black", - cable_dimensions : [ 0.0, 0.65, 4.5 ], // G4Tubs dimensions rmin, rmax, z - cable_position : [ 0.0, 0.0, -15.2 ], // x, y, z +construction: "hemisphere", +envelope_radius : 24.4, // should be large enough to fit all objects (>flange_rmax) +front_encapsulation_material : "nakano_acrylic", +rear_encapsulation_material: "acrylic_black", +flange_rmax : 24.3, // applies to acrylic and metal flange +encap_radius : 20.0, +encap_thickness : 0.8, +use_metal_flange : 1, +metal_flange_material : "stainless_steel", +metal_flange_dimensions : [ 21.0, 24.3, 0.4 ], // G4Tubs dimensions rmin, rmax, z +inside_encapsulation_material : "air", +use_optical_gel : 1, +optical_gel_material: "optical_grease", +optical_gel_sub_height : 15.0, // start from a dome full of gel of size encap_radius, e.g. height of ... +// gel dome left is (encap_radius - optical_gel_sub_height) +pmtposoffset : [ 0.0, 0.0, 9.8 ], +use_silica_bag : 1, +silica_bag_material : "acrylic_white", +silica_bag_dimensions : [ 1.8, 3.3, 0.3 ], // G4Box dimensions x, y, z +silica_bag_position: [ 0.0, 13.5, -7.4 ], // x, y, z +use_cable : 1, +cable_material : "acrylic_black", +cable_dimensions : [ 0.0, 0.65, 4.5 ], // G4Tubs dimensions rmin, rmax, z +cable_position : [ 0.0, 0.0, -15.2 ], // x, y, z } diff --git a/src/geo/include/RAT/PMTEncapsulationConstruction.hh b/src/geo/include/RAT/PMTEncapsulationConstruction.hh index 407e96c2..760ba566 100644 --- a/src/geo/include/RAT/PMTEncapsulationConstruction.hh +++ b/src/geo/include/RAT/PMTEncapsulationConstruction.hh @@ -12,8 +12,8 @@ namespace RAT { class PMTEncapsulationConstruction { public: - - static PMTEncapsulationConstruction *NewConstruction(DBLinkPtr encaptable, DBLinkPtr pmttable, G4LogicalVolume *mother); + static PMTEncapsulationConstruction *NewConstruction(DBLinkPtr encaptable, DBLinkPtr pmttable, + G4LogicalVolume *mother); PMTEncapsulationConstruction(std::string _name) : name(_name) {} @@ -23,7 +23,9 @@ class PMTEncapsulationConstruction { virtual G4LogicalVolume *BuildVolume(const std::string &prefix) = 0; - virtual G4PVPlacement *PlaceEncap(G4RotationMatrix *pmtrot, G4ThreeVector pmtpos, const std::string &name, G4LogicalVolume *logi_pmt, G4VPhysicalVolume *mother_phys, bool booleanSolid, int copyNo) = 0; + virtual G4PVPlacement *PlaceEncap(G4RotationMatrix *pmtrot, G4ThreeVector pmtpos, const std::string &name, + G4LogicalVolume *logi_pmt, G4VPhysicalVolume *mother_phys, bool booleanSolid, + int copyNo) = 0; protected: std::string name; diff --git a/src/geo/src/pmt/PMTEncapsulationConstruction.cc b/src/geo/src/pmt/PMTEncapsulationConstruction.cc index f927c521..f7d739c5 100644 --- a/src/geo/src/pmt/PMTEncapsulationConstruction.cc +++ b/src/geo/src/pmt/PMTEncapsulationConstruction.cc @@ -12,7 +12,8 @@ namespace RAT { -PMTEncapsulationConstruction *PMTEncapsulationConstruction::NewConstruction(DBLinkPtr encaptable, DBLinkPtr pmttable, G4LogicalVolume *mother) { +PMTEncapsulationConstruction *PMTEncapsulationConstruction::NewConstruction(DBLinkPtr encaptable, DBLinkPtr pmttable, + G4LogicalVolume *mother) { std::string construction = encaptable->Get("construction"); if (construction == "hemisphere") { return new HemisphereEncapsulation(encaptable, pmttable, mother); From d19bfe77db2f6ca0b0bcb82bd3c9decd378fd445 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Mon, 12 May 2025 19:53:28 +0100 Subject: [PATCH 20/52] updated line 146 which caused warning, missing =0 --- src/geo/src/pmt/HemisphereEncapsulation.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/geo/src/pmt/HemisphereEncapsulation.cc b/src/geo/src/pmt/HemisphereEncapsulation.cc index ca4e2c92..c4213671 100644 --- a/src/geo/src/pmt/HemisphereEncapsulation.cc +++ b/src/geo/src/pmt/HemisphereEncapsulation.cc @@ -240,9 +240,9 @@ G4LogicalVolume *HemisphereEncapsulation::BuildVolume(const std::string &prefix) // ---------- Logical volumes ---------- - G4LogicalVolume *envelope_log = 0, *front_encapsulation_log, *rear_encapsulation_log, *metal_flange_encapsulation_log; - G4LogicalVolume *inner_encapsulation_log = 0, *optical_gel_encapsulation_log, *silica_bag_encapsulation_log, - *cable_encapsulation_log; + G4LogicalVolume *envelope_log = 0, *front_encapsulation_log = 0, *rear_encapsulation_log = 0, *metal_flange_encapsulation_log = 0; + G4LogicalVolume *inner_encapsulation_log = 0, *optical_gel_encapsulation_log = 0, *silica_bag_encapsulation_log = 0, + *cable_encapsulation_log = 0; envelope_log = new G4LogicalVolume(envelope_solid, fParams.exterior_material, "envelope_log"); From 5e681c3b57b6dd60bc8554b2a11266d68d7fc24f Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Wed, 14 May 2025 17:35:58 +0100 Subject: [PATCH 21/52] small changes to remove warnings --- src/geo/src/pmt/HemisphereEncapsulation.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/geo/src/pmt/HemisphereEncapsulation.cc b/src/geo/src/pmt/HemisphereEncapsulation.cc index c4213671..1a77504f 100644 --- a/src/geo/src/pmt/HemisphereEncapsulation.cc +++ b/src/geo/src/pmt/HemisphereEncapsulation.cc @@ -240,8 +240,9 @@ G4LogicalVolume *HemisphereEncapsulation::BuildVolume(const std::string &prefix) // ---------- Logical volumes ---------- - G4LogicalVolume *envelope_log = 0, *front_encapsulation_log = 0, *rear_encapsulation_log = 0, *metal_flange_encapsulation_log = 0; - G4LogicalVolume *inner_encapsulation_log = 0, *optical_gel_encapsulation_log = 0, *silica_bag_encapsulation_log = 0, + G4LogicalVolume *envelope_log, *front_encapsulation_log, *rear_encapsulation_log, + *metal_flange_encapsulation_log = 0; + G4LogicalVolume *inner_encapsulation_log, *optical_gel_encapsulation_log = 0, *silica_bag_encapsulation_log = 0, *cable_encapsulation_log = 0; envelope_log = new G4LogicalVolume(envelope_solid, fParams.exterior_material, "envelope_log"); From b0e6adcf154830f93b2f03296c08096db92e453b Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Wed, 14 May 2025 17:37:40 +0100 Subject: [PATCH 22/52] small changes to remove warnings --- src/geo/src/pmt/HemisphereEncapsulation.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/geo/src/pmt/HemisphereEncapsulation.cc b/src/geo/src/pmt/HemisphereEncapsulation.cc index 1a77504f..ebfe6c60 100644 --- a/src/geo/src/pmt/HemisphereEncapsulation.cc +++ b/src/geo/src/pmt/HemisphereEncapsulation.cc @@ -240,10 +240,9 @@ G4LogicalVolume *HemisphereEncapsulation::BuildVolume(const std::string &prefix) // ---------- Logical volumes ---------- - G4LogicalVolume *envelope_log, *front_encapsulation_log, *rear_encapsulation_log, - *metal_flange_encapsulation_log = 0; + G4LogicalVolume *envelope_log, *front_encapsulation_log, *rear_encapsulation_log, *metal_flange_encapsulation_log = 0; G4LogicalVolume *inner_encapsulation_log, *optical_gel_encapsulation_log = 0, *silica_bag_encapsulation_log = 0, - *cable_encapsulation_log = 0; + *cable_encapsulation_log = 0; envelope_log = new G4LogicalVolume(envelope_solid, fParams.exterior_material, "envelope_log"); From 9d408c1a3ac88c2f6e0d486558347b0410ba045a Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Wed, 14 May 2025 17:38:45 +0100 Subject: [PATCH 23/52] added extra offset to pmt position for when PMT is not centre of encapsulation --- src/geo/src/pmt/PMTFactoryBase.cc | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/geo/src/pmt/PMTFactoryBase.cc b/src/geo/src/pmt/PMTFactoryBase.cc index 43dd1092..39346b34 100644 --- a/src/geo/src/pmt/PMTFactoryBase.cc +++ b/src/geo/src/pmt/PMTFactoryBase.cc @@ -51,8 +51,7 @@ G4VPhysicalVolume *PMTFactoryBase::ConstructPMTs( PMTConstruction *construction = 0; G4LogicalVolume *log_pmt = 0; G4VPhysicalVolume *phys_mother_encap = 0; - G4PVPlacement *envelope_phys = 0; - G4ThreeVector pmtposition(0.0, 0.0, 0.0); + G4ThreeVector pmtoffsetposition(0.0, 0.0, 0.0); int encapsulation = 0; // default to no encapsulation try { @@ -72,9 +71,9 @@ G4VPhysicalVolume *PMTFactoryBase::ConstructPMTs( try { std::vector posvector = lencapsulation->GetDArray("pmtposoffset"); - pmtposition.setX(posvector[0] * CLHEP::cm); - pmtposition.setY(posvector[1] * CLHEP::cm); - pmtposition.setZ(posvector[2] * CLHEP::cm); + pmtoffsetposition.setX(posvector[0] * CLHEP::cm); + pmtoffsetposition.setY(posvector[1] * CLHEP::cm); + pmtoffsetposition.setZ(posvector[2] * CLHEP::cm); } catch (DBNotFoundError &e) { }; @@ -94,7 +93,7 @@ G4VPhysicalVolume *PMTFactoryBase::ConstructPMTs( log_pmt = construction->BuildVolume(volume_name); if (encapsulation == 1) { - envelope_phys = new G4PVPlacement(0, pmtposition, volume_name + "_body_phys", log_pmt, phys_mother_encap, false, 0); + construction->PlacePMT(0, pmtoffsetposition, volume_name + "_body_phys", log_pmt, phys_mother_encap, false, 0); } /* BFields not in the database anywhere and should be looked at */ @@ -289,6 +288,20 @@ G4VPhysicalVolume *PMTFactoryBase::ConstructPMTs( // TODO: We should also account for a rotation of the mother volume at some point G4ThreeVector pmtpos_global = pmtpos + local_offset; + // PMT may have been placed offset from encapsulation origin + if (encapsulation == 1) { + G4ThreeVector extra_offset; + info << i << " " << pmtpos_global.x() << " " << pmtpos_global.y() << " " << pmtpos_global.z() << newline; + info << i << " " << pmtdir.x() << " " << pmtdir.y() << " " << pmtdir.z() << newline; + extra_offset.setX(pmtdir.x() * pmtoffsetposition.z()); + extra_offset.setY(pmtdir.y() * pmtoffsetposition.z()); + extra_offset.setZ(pmtdir.z() * pmtoffsetposition.z()); + info << i << " " << extra_offset.x() << " " << extra_offset.y() << " " << extra_offset.z() << newline; + pmtpos_global += extra_offset; + info << i << " " << pmtpos_global.x() << " " << pmtpos_global.y() << " " << pmtpos_global.z() << newline + << newline; + } + // Store individual efficiency EfficiencyCorrection[id] = pmt_effi_corr[i]; From 5b5c5400f84f09814d3b731ac65d7eb73fd93858 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Wed, 14 May 2025 18:10:00 +0100 Subject: [PATCH 24/52] changed units from cm to mm to keep consistent --- ratdb/ENCAPSULATION.ratdb | 22 +++---- src/geo/src/pmt/HemisphereEncapsulation.cc | 72 +++++++++++----------- src/geo/src/pmt/PMTFactoryBase.cc | 6 +- 3 files changed, 50 insertions(+), 50 deletions(-) diff --git a/ratdb/ENCAPSULATION.ratdb b/ratdb/ENCAPSULATION.ratdb index d1485602..a031c8a3 100644 --- a/ratdb/ENCAPSULATION.ratdb +++ b/ratdb/ENCAPSULATION.ratdb @@ -5,27 +5,27 @@ valid_begin : [ 0, 0 ], valid_end : [ 0, 0 ], construction: "hemisphere", -envelope_radius : 24.4, // should be large enough to fit all objects (>flange_rmax) +envelope_radius : 244.0, // should be large enough to fit all objects (>flange_rmax) front_encapsulation_material : "nakano_acrylic", rear_encapsulation_material: "acrylic_black", -flange_rmax : 24.3, // applies to acrylic and metal flange -encap_radius : 20.0, -encap_thickness : 0.8, +flange_rmax : 243.0, // applies to acrylic and metal flange +encap_radius : 200.0, +encap_thickness : 8.0, use_metal_flange : 1, metal_flange_material : "stainless_steel", -metal_flange_dimensions : [ 21.0, 24.3, 0.4 ], // G4Tubs dimensions rmin, rmax, z +metal_flange_dimensions : [ 220.0, 243.0, 4.0 ], // G4Tubs dimensions rmin, rmax, z inside_encapsulation_material : "air", use_optical_gel : 1, optical_gel_material: "optical_grease", -optical_gel_sub_height : 15.0, // start from a dome full of gel of size encap_radius, e.g. height of ... +optical_gel_sub_height : 150.0, // start from a dome full of gel of size encap_radius, e.g. height of ... // gel dome left is (encap_radius - optical_gel_sub_height) -pmtposoffset : [ 0.0, 0.0, 9.8 ], +pmtposoffset : [ 0.0, 0.0, 98.0 ], use_silica_bag : 1, silica_bag_material : "acrylic_white", -silica_bag_dimensions : [ 1.8, 3.3, 0.3 ], // G4Box dimensions x, y, z -silica_bag_position: [ 0.0, 13.5, -7.4 ], // x, y, z +silica_bag_dimensions : [ 18.0, 33.0, 3.0 ], // G4Box dimensions x, y, z +silica_bag_position: [ 0.0, 135.0, -74.0 ], // x, y, z use_cable : 1, cable_material : "acrylic_black", -cable_dimensions : [ 0.0, 0.65, 4.5 ], // G4Tubs dimensions rmin, rmax, z -cable_position : [ 0.0, 0.0, -15.2 ], // x, y, z +cable_dimensions : [ 0.0, 6.5, 45.0 ], // G4Tubs dimensions rmin, rmax, z +cable_position : [ 0.0, 0.0, -152.0 ], // x, y, z } diff --git a/src/geo/src/pmt/HemisphereEncapsulation.cc b/src/geo/src/pmt/HemisphereEncapsulation.cc index ebfe6c60..d499b922 100644 --- a/src/geo/src/pmt/HemisphereEncapsulation.cc +++ b/src/geo/src/pmt/HemisphereEncapsulation.cc @@ -114,9 +114,9 @@ HemisphereEncapsulation::HemisphereEncapsulation(DBLinkPtr encaptable, DBLinkPtr fParams.pmtposvec.setZ(0.0); try { fParams.posvec = encaptable->GetDArray("pmtposoffset"); - fParams.pmtposvec.setX(fParams.posvec[0] * CLHEP::cm); - fParams.pmtposvec.setY(fParams.posvec[1] * CLHEP::cm); - fParams.pmtposvec.setZ(fParams.posvec[2] * CLHEP::cm); + fParams.pmtposvec.setX(fParams.posvec[0] * CLHEP::mm); + fParams.pmtposvec.setY(fParams.posvec[1] * CLHEP::mm); + fParams.pmtposvec.setZ(fParams.posvec[2] * CLHEP::mm); } catch (DBNotFoundError &e) { }; } @@ -167,44 +167,44 @@ G4LogicalVolume *HemisphereEncapsulation::BuildVolume(const std::string &prefix) G4VSolid *front_encapsulation_solid = new G4Sphere("front_encapsulation_solid", - (fParams.encap_radius) * CLHEP::cm, // rmin - (fParams.encap_radius + fParams.encap_thickness) * CLHEP::cm, // rmax + (fParams.encap_radius) * CLHEP::mm, // rmin + (fParams.encap_radius + fParams.encap_thickness) * CLHEP::mm, // rmax 0.5 * CLHEP::pi, CLHEP::twopi, // phi 0.0, 0.5 * CLHEP::pi); // theta G4VSolid *rear_encapsulation_solid = new G4Sphere("rear_encapsulation_solid", - (fParams.encap_radius) * CLHEP::cm, // rmin - (fParams.encap_radius + fParams.encap_thickness) * CLHEP::cm, // rmax + (fParams.encap_radius) * CLHEP::mm, // rmin + (fParams.encap_radius + fParams.encap_thickness) * CLHEP::mm, // rmax 0.5 * CLHEP::pi, CLHEP::twopi, // phi 0.5 * CLHEP::pi, 0.5 * CLHEP::pi); // theta G4VSolid *dome_flange_solid = new G4Tubs("dome_flange_solid", - (fParams.encap_radius) * CLHEP::cm, // rmin - (fParams.flange_rmax) * CLHEP::cm, // rmax - (0.5 * fParams.encap_thickness) * CLHEP::cm, // zhalf, thickness is same as dome thickness so 0.8/2.0 + (fParams.encap_radius) * CLHEP::mm, // rmin + (fParams.flange_rmax) * CLHEP::mm, // rmax + (0.5 * fParams.encap_thickness) * CLHEP::mm, // zhalf, thickness is same as dome thickness so 0.8/2.0 0.0, CLHEP::twopi); // phi front_encapsulation_solid = new G4UnionSolid("front_encapsulation_solid", front_encapsulation_solid, dome_flange_solid, 0, - G4ThreeVector(0.0, 0.0, (0.5 * fParams.encap_thickness) * CLHEP::cm)); + G4ThreeVector(0.0, 0.0, (0.5 * fParams.encap_thickness) * CLHEP::mm)); rear_encapsulation_solid = new G4UnionSolid("rear_encapsulation_solid", rear_encapsulation_solid, dome_flange_solid, - 0, G4ThreeVector(0.0, 0.0, -(0.5 * fParams.encap_thickness) * CLHEP::cm)); + 0, G4ThreeVector(0.0, 0.0, -(0.5 * fParams.encap_thickness) * CLHEP::mm)); G4Tubs *metal_flange_solid = 0; if (fParams.useMetalFlange == 1) { metal_flange_solid = new G4Tubs("front_metal_flange_solid", - (fParams.metal_flange_dimensions[0]) * CLHEP::cm, // rmin - (fParams.metal_flange_dimensions[1]) * CLHEP::cm, // rmax - (fParams.metal_flange_dimensions[2]) * CLHEP::cm, // size z half + (fParams.metal_flange_dimensions[0]) * CLHEP::mm, // rmin + (fParams.metal_flange_dimensions[1]) * CLHEP::mm, // rmax + (fParams.metal_flange_dimensions[2]) * CLHEP::mm, // size z half 0.0, CLHEP::twopi); // phi } G4Sphere *inner_encapsulation_solid = new G4Sphere("inner_encapsulation_solid", - 0.0 * CLHEP::cm, // rmin - (fParams.encap_radius) * CLHEP::cm, // rmax + 0.0 * CLHEP::mm, // rmin + (fParams.encap_radius) * CLHEP::mm, // rmax 0.0, CLHEP::twopi, // phi 0.0, CLHEP::twopi); // theta @@ -225,16 +225,16 @@ G4LogicalVolume *HemisphereEncapsulation::BuildVolume(const std::string &prefix) G4Box *silica_bag_solid = 0; if (fParams.useSilicaBag == 1) { silica_bag_solid = - new G4Box("silica_bag_solid", (fParams.silica_bag_dimensions[0]) * CLHEP::cm, - (fParams.silica_bag_dimensions[1]) * CLHEP::cm, (fParams.silica_bag_dimensions[2]) * CLHEP::cm); + new G4Box("silica_bag_solid", (fParams.silica_bag_dimensions[0]) * CLHEP::mm, + (fParams.silica_bag_dimensions[1]) * CLHEP::mm, (fParams.silica_bag_dimensions[2]) * CLHEP::mm); } G4Tubs *cable_solid = 0; if (fParams.useCable == 1) { cable_solid = new G4Tubs("cable_solid", - (fParams.cable_dimensions[0]) * CLHEP::cm, // rmin - (fParams.cable_dimensions[1]) * CLHEP::cm, // rmax - (fParams.cable_dimensions[2]) * CLHEP::cm, // size z + (fParams.cable_dimensions[0]) * CLHEP::mm, // rmin + (fParams.cable_dimensions[1]) * CLHEP::mm, // rmax + (fParams.cable_dimensions[2]) * CLHEP::mm, // size z 0.0, CLHEP::twopi); // phi } @@ -278,7 +278,7 @@ G4LogicalVolume *HemisphereEncapsulation::BuildVolume(const std::string &prefix) front_encapsulation_phys = new G4PVPlacement(0, // rotation - G4ThreeVector(0.0, 0.0, 0.0 * CLHEP::cm), // position + G4ThreeVector(0.0, 0.0, 0.0), // position front_encapsulation_log, // the logical volume prefix + "_front_dome_encapsulation_phys", // a name for this physical volume envelope_log, // the mother volume @@ -287,7 +287,7 @@ G4LogicalVolume *HemisphereEncapsulation::BuildVolume(const std::string &prefix) rear_encapsulation_phys = new G4PVPlacement(0, // rotation - G4ThreeVector(0.0, 0.0, 0.0 * CLHEP::cm), // position + G4ThreeVector(0.0, 0.0, 0.0), // position rear_encapsulation_log, // the logical volume prefix + "_rear_dome_encapsulation_phys", // a name for this physical volume envelope_log, // the mother volume @@ -295,7 +295,7 @@ G4LogicalVolume *HemisphereEncapsulation::BuildVolume(const std::string &prefix) 0); // copy number if (fParams.useMetalFlange == 1) { - double metal_flange_zpos = (fParams.encap_thickness + fParams.metal_flange_dimensions[2]) * CLHEP::cm; + double metal_flange_zpos = (fParams.encap_thickness + fParams.metal_flange_dimensions[2]) * CLHEP::mm; front_metal_encapsulaion_flange_phys = new G4PVPlacement(0, // rotation G4ThreeVector(0.0, 0.0, metal_flange_zpos), // position @@ -317,7 +317,7 @@ G4LogicalVolume *HemisphereEncapsulation::BuildVolume(const std::string &prefix) inner_encapsulation_phys = new G4PVPlacement(0, // rotation - G4ThreeVector(0.0, 0.0, 0.0 * CLHEP::cm), // position + G4ThreeVector(0.0, 0.0, 0.0), // position inner_encapsulation_log, // the logical volume prefix + "_inner_volume_encapsulation_phys", // a name for this physical volume envelope_log, // the mother volume @@ -327,7 +327,7 @@ G4LogicalVolume *HemisphereEncapsulation::BuildVolume(const std::string &prefix) if (fParams.useGel == 1) { optical_gel_encapsulation_phys = new G4PVPlacement(0, // rotation - G4ThreeVector(0.0, 0.0, 0.0 * CLHEP::cm), // position + G4ThreeVector(0.0, 0.0, 0.0), // position optical_gel_encapsulation_log, // the logical volume prefix + "_gel_encapsulation_phys", // a name for this physical volume inner_encapsulation_log, // the mother volume @@ -336,8 +336,8 @@ G4LogicalVolume *HemisphereEncapsulation::BuildVolume(const std::string &prefix) } if (fParams.useSilicaBag == 1) { - G4ThreeVector silicaposition(fParams.silica_bag_position[0] * CLHEP::cm, fParams.silica_bag_position[1] * CLHEP::cm, - fParams.silica_bag_position[2] * CLHEP::cm); + G4ThreeVector silicaposition(fParams.silica_bag_position[0] * CLHEP::mm, fParams.silica_bag_position[1] * CLHEP::mm, + fParams.silica_bag_position[2] * CLHEP::mm); silica_bag_encapsulation_phys = new G4PVPlacement(0, // rotation @@ -350,8 +350,8 @@ G4LogicalVolume *HemisphereEncapsulation::BuildVolume(const std::string &prefix) } if (fParams.useCable == 1) { - G4ThreeVector cableposition(fParams.cable_position[0] * CLHEP::cm, fParams.cable_position[1] * CLHEP::cm, - fParams.cable_position[2] * CLHEP::cm); + G4ThreeVector cableposition(fParams.cable_position[0] * CLHEP::mm, fParams.cable_position[1] * CLHEP::mm, + fParams.cable_position[2] * CLHEP::mm); cable_encapsulation_phys = new G4PVPlacement(0, // rotation @@ -451,15 +451,15 @@ G4VSolid *HemisphereEncapsulation::BuildSolid(const std::string &_name) { G4VSolid *HemisphereEncapsulation::optical_gel_height_subtraction(const std::string &_name) { G4Sphere *optical_gel_1 = - new G4Sphere("optical_gel_1_encapsulation_solid", 0.0 * CLHEP::cm, (fParams.encap_radius) * CLHEP::cm, + new G4Sphere("optical_gel_1_encapsulation_solid", 0.0 * CLHEP::mm, (fParams.encap_radius) * CLHEP::mm, 0.5 * CLHEP::pi, CLHEP::twopi, 0.0, 0.5 * CLHEP::pi); G4Tubs *gel_subtract = new G4Tubs("gel_sub_solid", 0.0, - (fParams.encap_radius) * CLHEP::cm, // solid cylinder - (fParams.optical_gel_sub_height) * CLHEP::cm, // half height of cylinder + (fParams.encap_radius) * CLHEP::mm, // solid cylinder + (fParams.optical_gel_sub_height) * CLHEP::mm, // half height of cylinder 0.0, CLHEP::twopi); // cylinder complete in phi - return new G4SubtractionSolid(_name, optical_gel_1, gel_subtract, 0, G4ThreeVector(0.0, 0.0, 0.0 * CLHEP::cm)); + return new G4SubtractionSolid(_name, optical_gel_1, gel_subtract, 0, G4ThreeVector(0.0, 0.0, 0.0)); } G4VSolid *HemisphereEncapsulation::optical_gel_pmt_subtraction(const std::string &_name, GLG4TorusStack *body) { @@ -475,7 +475,7 @@ G4PVPlacement *HemisphereEncapsulation::PlaceEncap(G4RotationMatrix *pmtrot, G4T } G4VSolid *HemisphereEncapsulation::NewEnvelopeSolid(const std::string &_name) { - G4Sphere *outer_s = new G4Sphere(_name + "_main", 0. * CLHEP::mm, fParams.envelope_radius * CLHEP::cm, 0.0, + G4Sphere *outer_s = new G4Sphere(_name + "_main", 0. * CLHEP::mm, fParams.envelope_radius * CLHEP::mm, 0.0, CLHEP::twopi, 0.0, CLHEP::twopi); return outer_s; } diff --git a/src/geo/src/pmt/PMTFactoryBase.cc b/src/geo/src/pmt/PMTFactoryBase.cc index 39346b34..af5304a1 100644 --- a/src/geo/src/pmt/PMTFactoryBase.cc +++ b/src/geo/src/pmt/PMTFactoryBase.cc @@ -71,9 +71,9 @@ G4VPhysicalVolume *PMTFactoryBase::ConstructPMTs( try { std::vector posvector = lencapsulation->GetDArray("pmtposoffset"); - pmtoffsetposition.setX(posvector[0] * CLHEP::cm); - pmtoffsetposition.setY(posvector[1] * CLHEP::cm); - pmtoffsetposition.setZ(posvector[2] * CLHEP::cm); + pmtoffsetposition.setX(posvector[0] * CLHEP::mm); + pmtoffsetposition.setY(posvector[1] * CLHEP::mm); + pmtoffsetposition.setZ(posvector[2] * CLHEP::mm); } catch (DBNotFoundError &e) { }; From aa34f40829ff775a9507f2986abf07b245947241 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Mon, 19 May 2025 18:16:00 +0100 Subject: [PATCH 25/52] format update --- src/geo/src/pmt/HemisphereEncapsulation.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/geo/src/pmt/HemisphereEncapsulation.cc b/src/geo/src/pmt/HemisphereEncapsulation.cc index d499b922..1ff70497 100644 --- a/src/geo/src/pmt/HemisphereEncapsulation.cc +++ b/src/geo/src/pmt/HemisphereEncapsulation.cc @@ -278,7 +278,7 @@ G4LogicalVolume *HemisphereEncapsulation::BuildVolume(const std::string &prefix) front_encapsulation_phys = new G4PVPlacement(0, // rotation - G4ThreeVector(0.0, 0.0, 0.0), // position + G4ThreeVector(0.0, 0.0, 0.0), // position front_encapsulation_log, // the logical volume prefix + "_front_dome_encapsulation_phys", // a name for this physical volume envelope_log, // the mother volume @@ -287,7 +287,7 @@ G4LogicalVolume *HemisphereEncapsulation::BuildVolume(const std::string &prefix) rear_encapsulation_phys = new G4PVPlacement(0, // rotation - G4ThreeVector(0.0, 0.0, 0.0), // position + G4ThreeVector(0.0, 0.0, 0.0), // position rear_encapsulation_log, // the logical volume prefix + "_rear_dome_encapsulation_phys", // a name for this physical volume envelope_log, // the mother volume @@ -317,7 +317,7 @@ G4LogicalVolume *HemisphereEncapsulation::BuildVolume(const std::string &prefix) inner_encapsulation_phys = new G4PVPlacement(0, // rotation - G4ThreeVector(0.0, 0.0, 0.0), // position + G4ThreeVector(0.0, 0.0, 0.0), // position inner_encapsulation_log, // the logical volume prefix + "_inner_volume_encapsulation_phys", // a name for this physical volume envelope_log, // the mother volume @@ -326,12 +326,12 @@ G4LogicalVolume *HemisphereEncapsulation::BuildVolume(const std::string &prefix) if (fParams.useGel == 1) { optical_gel_encapsulation_phys = - new G4PVPlacement(0, // rotation - G4ThreeVector(0.0, 0.0, 0.0), // position - optical_gel_encapsulation_log, // the logical volume - prefix + "_gel_encapsulation_phys", // a name for this physical volume - inner_encapsulation_log, // the mother volume - false, // no boolean ops + new G4PVPlacement(0, // rotation + G4ThreeVector(0.0, 0.0, 0.0), // position + optical_gel_encapsulation_log, // the logical volume + prefix + "_gel_encapsulation_phys", // a name for this physical volume + inner_encapsulation_log, // the mother volume + false, // no boolean ops 0); } From 4accae06d4e132b5481d77b849c48255df0124f7 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Mon, 19 May 2025 18:29:55 +0100 Subject: [PATCH 26/52] removed cout lines for offset check --- src/geo/src/pmt/PMTFactoryBase.cc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/geo/src/pmt/PMTFactoryBase.cc b/src/geo/src/pmt/PMTFactoryBase.cc index af5304a1..ba2b8eb6 100644 --- a/src/geo/src/pmt/PMTFactoryBase.cc +++ b/src/geo/src/pmt/PMTFactoryBase.cc @@ -288,18 +288,13 @@ G4VPhysicalVolume *PMTFactoryBase::ConstructPMTs( // TODO: We should also account for a rotation of the mother volume at some point G4ThreeVector pmtpos_global = pmtpos + local_offset; - // PMT may have been placed offset from encapsulation origin + // PMT may have been placed offset from encapsulation origin, assume pmt only moved forward/backwards (z position change) if (encapsulation == 1) { G4ThreeVector extra_offset; - info << i << " " << pmtpos_global.x() << " " << pmtpos_global.y() << " " << pmtpos_global.z() << newline; - info << i << " " << pmtdir.x() << " " << pmtdir.y() << " " << pmtdir.z() << newline; extra_offset.setX(pmtdir.x() * pmtoffsetposition.z()); extra_offset.setY(pmtdir.y() * pmtoffsetposition.z()); extra_offset.setZ(pmtdir.z() * pmtoffsetposition.z()); - info << i << " " << extra_offset.x() << " " << extra_offset.y() << " " << extra_offset.z() << newline; pmtpos_global += extra_offset; - info << i << " " << pmtpos_global.x() << " " << pmtpos_global.y() << " " << pmtpos_global.z() << newline - << newline; } // Store individual efficiency From aaf7adf0588058813400c8dd377a5075e3476935 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Mon, 19 May 2025 19:12:20 +0100 Subject: [PATCH 27/52] format changes --- src/geo/src/pmt/PMTFactoryBase.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/geo/src/pmt/PMTFactoryBase.cc b/src/geo/src/pmt/PMTFactoryBase.cc index ba2b8eb6..f38892dc 100644 --- a/src/geo/src/pmt/PMTFactoryBase.cc +++ b/src/geo/src/pmt/PMTFactoryBase.cc @@ -288,7 +288,8 @@ G4VPhysicalVolume *PMTFactoryBase::ConstructPMTs( // TODO: We should also account for a rotation of the mother volume at some point G4ThreeVector pmtpos_global = pmtpos + local_offset; - // PMT may have been placed offset from encapsulation origin, assume pmt only moved forward/backwards (z position change) + // PMT may have been placed offset from encapsulation origin, assume pmt only moved forward/backwards (z position + // change) if (encapsulation == 1) { G4ThreeVector extra_offset; extra_offset.setX(pmtdir.x() * pmtoffsetposition.z()); From 0d637851ea56f3a14578a37bbd1af3212415a647 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Tue, 20 May 2025 21:56:33 +0100 Subject: [PATCH 28/52] created pmt encapsulation documentation --- doc/users_guide/pmt.rst | 81 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/doc/users_guide/pmt.rst b/doc/users_guide/pmt.rst index 2df6be1e..fa5a3d47 100644 --- a/doc/users_guide/pmt.rst +++ b/doc/users_guide/pmt.rst @@ -4,6 +4,8 @@ PMT Simulation RAT uses a custom PMT simulation extracted from GLG4Sim. +---------------- + Q/T Response ```````````` Gsim checks the database for single photoelectron charge and transit time PDFs @@ -26,6 +28,8 @@ phenomenological model used by MiniCLEAN. * ``time`` - "x" values of the time PDF (nanoseconds) * ``time_prob`` - "y" values of the time PDF (will be normalized) +---------------- + Dark Current ```````````` @@ -112,3 +116,80 @@ All are stored in DAQ.ratdb noise_rate: 500.0d, // The mean noise rate across all PMTs, in Hz PMTnoise: [], // an array with 92 entries: individual noise rates per PMT, in Hz noise_flag: 0, // the flag to determine which noise model you use (default is to turn noise off completely) + +---------------- + +PMT Afterpulsing +````````````````` + +Details of PMT afterpulsing + +---------------- + +PMT Pulse Generation +```````````````````` + +Details of the PMT pulse generation here. + +---------------- + +PMT Encapsulation +````````````````` + +PMT encapsulation is used for several reasons, such as to ensure compatability with multiple detection media (e.g. air, water, doped water). + +The encapsulation code was originally created for the BUTTON experiment, in which each of the 96 PMTs used are enclosed by two hemisphere domes that are sealed together by metal flanges and bolts. +The encapsulation code structure is based off the PMT construction structure, in which a instance is initialised depending on the construction type given. +When enabled, the encapsulation object is created first, followed the pmt object. The PMT is then placed inside the encapsulation before itself is placed in the mother volume given. + +Enabling Encapsulation +'''''''''' +Encapsulation by default is turned off. +In a .geo file, it can be enabled by adding the following line inside the ``inner_pmts`` index entry: +:: encapsulation: 1, +With 0 being off. +It can also be added in a macro with: +:: /rat/db/set GEO[inner_pmts] encapsulation 1 + +The other line that must be included inside the ``inner_pmts`` index entry is the model type: +:: encapsulation_model: "model", +Where "model" must match an index entry name in ``ENCAPSULATION.ratdb``. + +Encapsulation model information +'''''''''' +Encapsulation models need to be added to ``ENCAPSULATION.ratdb``, which is loacted in ``ratpac/ratdb``. +A entry can be called by using the ``encapsulation_model:`` command as mentioned above. +Each entry provides all the important information that is needed to create the encapsulation objects: + +Construction type +Enable and disable additional objects +Object dimensions and materials +Off-centre object placements + +The construction type is needed to ensure the correct encapsulation construction class is loaded. This represents the general shape of the encapsulation used. +Multiple entries can use the same construction type, which can vary on the objects and object properties used. + +Adding a new Encapsulation construction +'''''''''' +Initially, the only encapsulation construction is the "hemisphere" type, which encapsulates the PMT inside two hemispheres. +An inner volume is then created in which the PMT can be placed. + +To create a different encapsulation construction (e.g. a box), the option must be added to ``PMTEncapsulationConstruction.cc``. +This file uses the construction type that is given in the called ``ENCAPSULATION.ratdb`` entry to initiate the associated encapsulation construction. +For a working example please see ``HemisphereEncapsulation.cc/hh`` which uses the "hemisphere" construction type. + +A new encapsulation construction should make the encapsulation creation as customisable as possible. +The important object imformation such as those stated above should be called from an ``ENCAPSULATION.ratdb`` entry. + +Placing PMT +'''''''''' +If encapsulation is used, then is possible that the medium inside the encapsuation is different to the mother volume medium it would be placed in without encapsulation on. +This can be change in ``PMTFactoryBase.cc`` to ensure that the correct mother volume is used for the placement. If using the visualiser, the scene tree is useful to see if the PMT has been placed inside the correct volume. + + +PMT Offset +'''''''''' +The encapsulation is placed using the PMT position(s) and direction(s) given, this means that the PMT is initially placed in the centre of the encapsulation. +An offset can be given in the ``ENCAPSULATION.ratdb`` entry so that the PMT is placed off-centre inside the encapsulation. This currently works for z-axis offsets (i.e move the PMT closer forwards/backwards). + +---------------- \ No newline at end of file From 113f1d72857676f5c2e849f93a2b9e6c641210d2 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Tue, 20 May 2025 22:04:12 +0100 Subject: [PATCH 29/52] created pmt encapsulation documentation --- doc/users_guide/pmt.rst | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/doc/users_guide/pmt.rst b/doc/users_guide/pmt.rst index fa5a3d47..82b7efd4 100644 --- a/doc/users_guide/pmt.rst +++ b/doc/users_guide/pmt.rst @@ -139,20 +139,25 @@ PMT Encapsulation PMT encapsulation is used for several reasons, such as to ensure compatability with multiple detection media (e.g. air, water, doped water). The encapsulation code was originally created for the BUTTON experiment, in which each of the 96 PMTs used are enclosed by two hemisphere domes that are sealed together by metal flanges and bolts. -The encapsulation code structure is based off the PMT construction structure, in which a instance is initialised depending on the construction type given. -When enabled, the encapsulation object is created first, followed the pmt object. The PMT is then placed inside the encapsulation before itself is placed in the mother volume given. + The encapsulation code structure is based off the PMT construction structure, in which a instance is initialised depending on the construction type given. + When enabled, the encapsulation object is created first, followed the pmt object. The PMT is then placed inside the encapsulation before itself is placed in the mother volume given. Enabling Encapsulation '''''''''' Encapsulation by default is turned off. -In a .geo file, it can be enabled by adding the following line inside the ``inner_pmts`` index entry: -:: encapsulation: 1, +In a .geo file, it can be enabled by adding the following line inside the ``inner_pmts`` index entry: :: + + encapsulation: 1, + With 0 being off. -It can also be added in a macro with: -:: /rat/db/set GEO[inner_pmts] encapsulation 1 +It can also be added in a macro with: :: + + /rat/db/set GEO[inner_pmts] encapsulation 1 + +The other line that must be included inside the ``inner_pmts`` index entry is the model type: :: + + encapsulation_model: "model", -The other line that must be included inside the ``inner_pmts`` index entry is the model type: -:: encapsulation_model: "model", Where "model" must match an index entry name in ``ENCAPSULATION.ratdb``. Encapsulation model information @@ -161,10 +166,10 @@ Encapsulation models need to be added to ``ENCAPSULATION.ratdb``, which is loact A entry can be called by using the ``encapsulation_model:`` command as mentioned above. Each entry provides all the important information that is needed to create the encapsulation objects: -Construction type -Enable and disable additional objects -Object dimensions and materials -Off-centre object placements +* Construction type +* Enable and disable additional objects +* Object dimensions and materials +* Off-centre object placements The construction type is needed to ensure the correct encapsulation construction class is loaded. This represents the general shape of the encapsulation used. Multiple entries can use the same construction type, which can vary on the objects and object properties used. From f3699599f849cd7a3e8b934832b77379fe129563 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Tue, 20 May 2025 22:08:52 +0100 Subject: [PATCH 30/52] created pmt encapsulation documentation --- doc/users_guide/pmt.rst | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/users_guide/pmt.rst b/doc/users_guide/pmt.rst index 82b7efd4..adbcdbaf 100644 --- a/doc/users_guide/pmt.rst +++ b/doc/users_guide/pmt.rst @@ -139,8 +139,10 @@ PMT Encapsulation PMT encapsulation is used for several reasons, such as to ensure compatability with multiple detection media (e.g. air, water, doped water). The encapsulation code was originally created for the BUTTON experiment, in which each of the 96 PMTs used are enclosed by two hemisphere domes that are sealed together by metal flanges and bolts. - The encapsulation code structure is based off the PMT construction structure, in which a instance is initialised depending on the construction type given. - When enabled, the encapsulation object is created first, followed the pmt object. The PMT is then placed inside the encapsulation before itself is placed in the mother volume given. + +The encapsulation code structure is based off the PMT construction structure, in which a instance is initialised depending on the construction type given. + +When enabled, the encapsulation object is created first, followed the pmt object. The PMT is then placed inside the encapsulation before itself is placed in the mother volume given. Enabling Encapsulation '''''''''' @@ -156,9 +158,9 @@ It can also be added in a macro with: :: The other line that must be included inside the ``inner_pmts`` index entry is the model type: :: - encapsulation_model: "model", + encapsulation_model: "modelname", -Where "model" must match an index entry name in ``ENCAPSULATION.ratdb``. +Where "modelname" must match an index entry name in ``ENCAPSULATION.ratdb``. Encapsulation model information '''''''''' From d2b35e2e0084fa968e10cdf09ba245f0af399174 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Tue, 20 May 2025 22:29:33 +0100 Subject: [PATCH 31/52] created pmt encapsulation documentation --- doc/users_guide/pmt.rst | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/doc/users_guide/pmt.rst b/doc/users_guide/pmt.rst index adbcdbaf..c447e047 100644 --- a/doc/users_guide/pmt.rst +++ b/doc/users_guide/pmt.rst @@ -173,21 +173,29 @@ Each entry provides all the important information that is needed to create the e * Object dimensions and materials * Off-centre object placements -The construction type is needed to ensure the correct encapsulation construction class is loaded. This represents the general shape of the encapsulation used. -Multiple entries can use the same construction type, which can vary on the objects and object properties used. +The construction type is needed to ensure the correct encapsulation construction is loaded. This represents the general shape of the encapsulation used. +For any materials used, their properties should be defined in ``MATERIALS.ratdb`` and ``OPTICS.ratdb``. +Any values given such as dimensions and positions should be given in mm. +Multiple entries can use the same construction type, but can vary on the objects and object properties used. Adding a new Encapsulation construction '''''''''' Initially, the only encapsulation construction is the "hemisphere" type, which encapsulates the PMT inside two hemispheres. An inner volume is then created in which the PMT can be placed. -To create a different encapsulation construction (e.g. a box), the option must be added to ``PMTEncapsulationConstruction.cc``. +When creating a new construction model (e.g. a box), the .cc file should contain three main functions: + +* An initial function that is called to create an instance with the information from the given ``ENCAPSULATION.ratdb`` entry. +* A build function that creates and returns the encapsulation. +* A placement function. + +A new encapsulation construction should make the build as customisable as possible. +The important object information such as those stated above should be called from an ``ENCAPSULATION.ratdb`` entry. + +To use a new construction type, the option must be added to ``PMTEncapsulationConstruction.cc``. This file uses the construction type that is given in the called ``ENCAPSULATION.ratdb`` entry to initiate the associated encapsulation construction. For a working example please see ``HemisphereEncapsulation.cc/hh`` which uses the "hemisphere" construction type. -A new encapsulation construction should make the encapsulation creation as customisable as possible. -The important object imformation such as those stated above should be called from an ``ENCAPSULATION.ratdb`` entry. - Placing PMT '''''''''' If encapsulation is used, then is possible that the medium inside the encapsuation is different to the mother volume medium it would be placed in without encapsulation on. From efc0ae9db42f95adfaec79714cca4ff8dbcaa72a Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Tue, 20 May 2025 22:34:15 +0100 Subject: [PATCH 32/52] created pmt encapsulation documentation --- doc/users_guide/pmt.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/users_guide/pmt.rst b/doc/users_guide/pmt.rst index c447e047..f37917a9 100644 --- a/doc/users_guide/pmt.rst +++ b/doc/users_guide/pmt.rst @@ -204,7 +204,7 @@ This can be change in ``PMTFactoryBase.cc`` to ensure that the correct mother vo PMT Offset '''''''''' -The encapsulation is placed using the PMT position(s) and direction(s) given, this means that the PMT is initially placed in the centre of the encapsulation. -An offset can be given in the ``ENCAPSULATION.ratdb`` entry so that the PMT is placed off-centre inside the encapsulation. This currently works for z-axis offsets (i.e move the PMT closer forwards/backwards). +The encapsulation is placed using the PMT position(s) and direction(s) given, this means that by default the PMT is placed in the centre of the encapsulation. +An offset can be given in the ``ENCAPSULATION.ratdb`` entry so that the PMT is placed off-centre inside the encapsulation. This currently works for z-axis offsets (i.e move the PMT forwards/backwards). ---------------- \ No newline at end of file From 813e308c8a55c74b4926e2b155cf7e70f94bac0a Mon Sep 17 00:00:00 2001 From: LSexton2396 <62307034+LSexton2396@users.noreply.github.com> Date: Tue, 20 May 2025 23:33:36 +0100 Subject: [PATCH 33/52] Delete doc/users_guide/pmt.rst to resolve conflict --- doc/users_guide/pmt.rst | 210 ---------------------------------------- 1 file changed, 210 deletions(-) delete mode 100644 doc/users_guide/pmt.rst diff --git a/doc/users_guide/pmt.rst b/doc/users_guide/pmt.rst deleted file mode 100644 index f37917a9..00000000 --- a/doc/users_guide/pmt.rst +++ /dev/null @@ -1,210 +0,0 @@ -PMT Simulation --------------- -(Need to update this section, it is mostly out of date) - -RAT uses a custom PMT simulation extracted from GLG4Sim. - ----------------- - -Q/T Response -```````````` -Gsim checks the database for single photoelectron charge and transit time PDFs -automatically for PMT models that are added to the geometry. These PDFs are -stored in tables named ``PMTCHARGE`` and ``PMTTRANSIT`` respectively, where the -index corresponds to a ``pmt_model`` field used in ``GEO`` tables. These PDFs -are sampled whenever a photon is absorbed by the photocathode to create a -realistic Q/T response automatically for PMTs independent of any DAQ processor. -If no tables are defined for a ``pmt_model`` the time defaults to approximately -zero spread from photoelectron absorption time and the charge defaults to a -phenomenological model used by MiniCLEAN. - -``PMTCHARGE`` fields: - * ``charge`` - "x" values of the charge PDF (arbitrary units) - * ``charge_prob`` - "y" values of the charge PDF (will be normalized) - - -``PMTTRANSIT`` fields: - * ``cable_delay`` - constant offset applied to all PMTs of this model (nanoseconds) - * ``time`` - "x" values of the time PDF (nanoseconds) - * ``time_prob`` - "y" values of the time PDF (will be normalized) - ----------------- - -Dark Current -```````````` - -PMTs have an intrinsic noise rate, or "dark current", which results from -thermal excitation at the single electron level. These thermal electrons can -exactly mimic a photoelectron from the PMT's photocathode and, thus, noise hits -cannot be distinguished from 'true' hits caused by incident photons. - -On the upside, this makes the noise hits fairly simple to simulate: we can draw -from the same charge spectrum as is used for regular PMT hits. The only -subtleties are in the timing distribution of the hits, and the rates at which -noise is generated. This document describes the inclusion of noise hits in -RAT. - -There old noise processor (source:rat/src/daq/NoiseProc.cc) had several -problems with the implementation, in particular the hits were incorrectly -distributed in time (generated for one sampling window width from the start of -the simulated event, therefore not extending throughout the event window), and -noise was defined in terms of a number of hits per event instead of a rate -(which is what we are more likely to measure). In addition, under the -principle of "apathy should lead to the most realistic simulation possible" (- -Dr Stanley Seibert), it was decided to incorporate noise hits into the default -event simulation, rather than retaining the optional processor. This avoids -the possibility of noise not being included either through forgetfulness, or -because the noise processor was run in the wrong order, for example after the -DAQ processors. As a result, running RAT will now include PMT noise hits by -default, unless they are switched off. Details on how to do so follow. - -Control -''''''' -There are three options for the inclusion of noise, as follows: - -0: No noise hits simulated. -1: Average noise rate read from 'noise_rate' in DAQ.ratdb. -2: Tube-by-tube noise rates read from 'PMTnoise' in DAQ.ratdb. - -These options are controlled by the use of the 'noise_flag', in the DAQ.ratdb -file. This flag can be include' in RAT macros as follows:: - - /rat/db/set DAQ noise_flag x - -where x = 0, 1, or 2, depending on the noise model chosen. - -The noise is included in the simulation after the physics event has been -propagated (all particles followed to extinction, and PMT hits recorded) but -before the DAQ, which runs as a separate processor. All noise hits are flagged -with the 'isNoise' bit in the MCPhoton class (set to 1 for noise hits, and 0 -for regular PMT hits). - -Timing Distribution -''''''''''''''''''' -Noise hits are generated uniformly in time, throughout a pre-defined 'noise -window'. The DAQ records data beginning from a predefined time before a -trigger. This time period (pretrigger time) is given by a fixed number -(currently 1350) of sampling windows (4ns each). We want noise to be simulated -throughout any recorded waveform. The noise window therefore begins at a time -before the first photon hit given by this pretrigger time. To allow for a -noise hit in coincidence with the last recorded photon to cause a trigger, the -noise window continues until the width of the event window, plus the width of a -single discriminator pulse, past the last photon hit time. - -Speed and file size Comparison -'''''''''''''''''''''''''''''' -To determine the effect of including noise in the default simulation, I -generated 1000 isotropic 20keV electrons at the centre of the detector using -each noise model. Both the average and the individual tube noise rates were -set to 2000Hz, to emphasise any impact of including noise hits (default is -500Hz). The results, in terms of CPU usage (output file size), were as -follows: - -Noise model 0: 2280.91 s (46M) -Noise model 1: 2285.77 s (48M) -Noise model 2: 2341.45 s (48M) - -So including noise in the simulation increases the processing time by 0.2%, and -simulating noise tube-by-tube increases it by a further 2.4%. - -The file size increased by ~5% when noise was included in the simulation. - -Parameters -'''''''''' -All are stored in DAQ.ratdb - -noise_rate: 500.0d, // The mean noise rate across all PMTs, in Hz -PMTnoise: [], // an array with 92 entries: individual noise rates per PMT, in Hz -noise_flag: 0, // the flag to determine which noise model you use (default is to turn noise off completely) - ----------------- - -PMT Afterpulsing -````````````````` - -Details of PMT afterpulsing - ----------------- - -PMT Pulse Generation -```````````````````` - -Details of the PMT pulse generation here. - ----------------- - -PMT Encapsulation -````````````````` - -PMT encapsulation is used for several reasons, such as to ensure compatability with multiple detection media (e.g. air, water, doped water). - -The encapsulation code was originally created for the BUTTON experiment, in which each of the 96 PMTs used are enclosed by two hemisphere domes that are sealed together by metal flanges and bolts. - -The encapsulation code structure is based off the PMT construction structure, in which a instance is initialised depending on the construction type given. - -When enabled, the encapsulation object is created first, followed the pmt object. The PMT is then placed inside the encapsulation before itself is placed in the mother volume given. - -Enabling Encapsulation -'''''''''' -Encapsulation by default is turned off. -In a .geo file, it can be enabled by adding the following line inside the ``inner_pmts`` index entry: :: - - encapsulation: 1, - -With 0 being off. -It can also be added in a macro with: :: - - /rat/db/set GEO[inner_pmts] encapsulation 1 - -The other line that must be included inside the ``inner_pmts`` index entry is the model type: :: - - encapsulation_model: "modelname", - -Where "modelname" must match an index entry name in ``ENCAPSULATION.ratdb``. - -Encapsulation model information -'''''''''' -Encapsulation models need to be added to ``ENCAPSULATION.ratdb``, which is loacted in ``ratpac/ratdb``. -A entry can be called by using the ``encapsulation_model:`` command as mentioned above. -Each entry provides all the important information that is needed to create the encapsulation objects: - -* Construction type -* Enable and disable additional objects -* Object dimensions and materials -* Off-centre object placements - -The construction type is needed to ensure the correct encapsulation construction is loaded. This represents the general shape of the encapsulation used. -For any materials used, their properties should be defined in ``MATERIALS.ratdb`` and ``OPTICS.ratdb``. -Any values given such as dimensions and positions should be given in mm. -Multiple entries can use the same construction type, but can vary on the objects and object properties used. - -Adding a new Encapsulation construction -'''''''''' -Initially, the only encapsulation construction is the "hemisphere" type, which encapsulates the PMT inside two hemispheres. -An inner volume is then created in which the PMT can be placed. - -When creating a new construction model (e.g. a box), the .cc file should contain three main functions: - -* An initial function that is called to create an instance with the information from the given ``ENCAPSULATION.ratdb`` entry. -* A build function that creates and returns the encapsulation. -* A placement function. - -A new encapsulation construction should make the build as customisable as possible. -The important object information such as those stated above should be called from an ``ENCAPSULATION.ratdb`` entry. - -To use a new construction type, the option must be added to ``PMTEncapsulationConstruction.cc``. -This file uses the construction type that is given in the called ``ENCAPSULATION.ratdb`` entry to initiate the associated encapsulation construction. -For a working example please see ``HemisphereEncapsulation.cc/hh`` which uses the "hemisphere" construction type. - -Placing PMT -'''''''''' -If encapsulation is used, then is possible that the medium inside the encapsuation is different to the mother volume medium it would be placed in without encapsulation on. -This can be change in ``PMTFactoryBase.cc`` to ensure that the correct mother volume is used for the placement. If using the visualiser, the scene tree is useful to see if the PMT has been placed inside the correct volume. - - -PMT Offset -'''''''''' -The encapsulation is placed using the PMT position(s) and direction(s) given, this means that by default the PMT is placed in the centre of the encapsulation. -An offset can be given in the ``ENCAPSULATION.ratdb`` entry so that the PMT is placed off-centre inside the encapsulation. This currently works for z-axis offsets (i.e move the PMT forwards/backwards). - ----------------- \ No newline at end of file From d5d379ac74d2e63999041bc68deb356eb11aa114 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Wed, 21 May 2025 14:37:19 +0100 Subject: [PATCH 34/52] added original pmt.rst back --- doc/users_guide/pmt.rst | 135 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 doc/users_guide/pmt.rst diff --git a/doc/users_guide/pmt.rst b/doc/users_guide/pmt.rst new file mode 100644 index 00000000..6bcebdf5 --- /dev/null +++ b/doc/users_guide/pmt.rst @@ -0,0 +1,135 @@ +PMT Simulation +-------------- +(Need to update this section, it is mostly out of date) + +RAT uses a custom PMT simulation extracted from GLG4Sim. + +---------------- + +Q/T Response +```````````` +Gsim checks the database for single photoelectron charge and transit time PDFs +automatically for PMT models that are added to the geometry. These PDFs are +stored in tables named ``PMTCHARGE`` and ``PMTTRANSIT`` respectively, where the +index corresponds to a ``pmt_model`` field used in ``GEO`` tables. These PDFs +are sampled whenever a photon is absorbed by the photocathode to create a +realistic Q/T response automatically for PMTs independent of any DAQ processor. +If no tables are defined for a ``pmt_model`` the time defaults to approximately +zero spread from photoelectron absorption time and the charge defaults to a +phenomenological model used by MiniCLEAN. + +``PMTCHARGE`` fields: + * ``charge`` - "x" values of the charge PDF (arbitrary units) + * ``charge_prob`` - "y" values of the charge PDF (will be normalized) + + +``PMTTRANSIT`` fields: + * ``cable_delay`` - constant offset applied to all PMTs of this model (nanoseconds) + * ``time`` - "x" values of the time PDF (nanoseconds) + * ``time_prob`` - "y" values of the time PDF (will be normalized) + +---------------- + +Dark Current +```````````` + +PMTs have an intrinsic noise rate, or "dark current", which results from +thermal excitation at the single electron level. These thermal electrons can +exactly mimic a photoelectron from the PMT's photocathode and, thus, noise hits +cannot be distinguished from 'true' hits caused by incident photons. + +On the upside, this makes the noise hits fairly simple to simulate: we can draw +from the same charge spectrum as is used for regular PMT hits. The only +subtleties are in the timing distribution of the hits, and the rates at which +noise is generated. This document describes the inclusion of noise hits in +RAT. + +There old noise processor (source:rat/src/daq/NoiseProc.cc) had several +problems with the implementation, in particular the hits were incorrectly +distributed in time (generated for one sampling window width from the start of +the simulated event, therefore not extending throughout the event window), and +noise was defined in terms of a number of hits per event instead of a rate +(which is what we are more likely to measure). In addition, under the +principle of "apathy should lead to the most realistic simulation possible" (- +Dr Stanley Seibert), it was decided to incorporate noise hits into the default +event simulation, rather than retaining the optional processor. This avoids +the possibility of noise not being included either through forgetfulness, or +because the noise processor was run in the wrong order, for example after the +DAQ processors. As a result, running RAT will now include PMT noise hits by +default, unless they are switched off. Details on how to do so follow. + +Control +''''''' +There are three options for the inclusion of noise, as follows: + +0: No noise hits simulated. +1: Average noise rate read from 'noise_rate' in DAQ.ratdb. +2: Tube-by-tube noise rates read from 'PMTnoise' in DAQ.ratdb. + +These options are controlled by the use of the 'noise_flag', in the DAQ.ratdb +file. This flag can be include' in RAT macros as follows:: + + /rat/db/set DAQ noise_flag x + +where x = 0, 1, or 2, depending on the noise model chosen. + +The noise is included in the simulation after the physics event has been +propagated (all particles followed to extinction, and PMT hits recorded) but +before the DAQ, which runs as a separate processor. All noise hits are flagged +with the 'isNoise' bit in the MCPhoton class (set to 1 for noise hits, and 0 +for regular PMT hits). + +Timing Distribution +''''''''''''''''''' +Noise hits are generated uniformly in time, throughout a pre-defined 'noise +window'. The DAQ records data beginning from a predefined time before a +trigger. This time period (pretrigger time) is given by a fixed number +(currently 1350) of sampling windows (4ns each). We want noise to be simulated +throughout any recorded waveform. The noise window therefore begins at a time +before the first photon hit given by this pretrigger time. To allow for a +noise hit in coincidence with the last recorded photon to cause a trigger, the +noise window continues until the width of the event window, plus the width of a +single discriminator pulse, past the last photon hit time. + +Speed and file size Comparison +'''''''''''''''''''''''''''''' +To determine the effect of including noise in the default simulation, I +generated 1000 isotropic 20keV electrons at the centre of the detector using +each noise model. Both the average and the individual tube noise rates were +set to 2000Hz, to emphasise any impact of including noise hits (default is +500Hz). The results, in terms of CPU usage (output file size), were as +follows: + +Noise model 0: 2280.91 s (46M) +Noise model 1: 2285.77 s (48M) +Noise model 2: 2341.45 s (48M) + +So including noise in the simulation increases the processing time by 0.2%, and +simulating noise tube-by-tube increases it by a further 2.4%. + +The file size increased by ~5% when noise was included in the simulation. + +Parameters +'''''''''' +All are stored in DAQ.ratdb + +noise_rate: 500.0d, // The mean noise rate across all PMTs, in Hz +PMTnoise: [], // an array with 92 entries: individual noise rates per PMT, in Hz +noise_flag: 0, // the flag to determine which noise model you use (default is to turn noise off completely) + +---------------- + +PMT Afterpulsing +````````````````` + +Details of PMT afterpulsing + +---------------- + +PMT Pulse Generation +```````````````````` + +Details of the PMT pulse generation here. + +---------------- + From ca32b0aea4bbe6f23eef5ccf344eb2926d4419c7 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Tue, 3 Jun 2025 16:59:34 +0100 Subject: [PATCH 35/52] removed old encapsulated pmt entry, no longer used --- ratdb/PMT.ratdb | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/ratdb/PMT.ratdb b/ratdb/PMT.ratdb index d9e26e17..3e7959a4 100644 --- a/ratdb/PMT.ratdb +++ b/ratdb/PMT.ratdb @@ -451,45 +451,6 @@ z_origin: [ -40.0, 0.0, 0.0, 40.0, -142.0 ], noise_rate: 10000.0, // Hz } -{ -//An encapsulated version of the pmt -name: "PMT", -index: "r7081pe_encapsulated", -valid_begin: [0,0], -valid_end: [0,0], - -construction: "encapsulated", - -dynode_material: "stainless_steel", -glass_material: "hamamatsu_borosilicate_glass", -pmt_vacuum_material: "pmt_vacuum", -photocathode_surface: "photocathode_R7081", -photocathode_MINrho: 110.0, -photocathode_MAXrho: 126.5, -mirror_surface: "mirror", -dynode_surface: "stainless_steel", - -front_encapsulation_material: "nakano_acrylic", -rear_encapsulation_material: "acrylic_black", -metal_flange_material: "stainless_steel", -acrylic_flange_material: "nakano_acrylic", -silica_bag_material: "acrylic_white", -cable_material: "acrylic_black", -inside_encapsulation_material: "air", -optical_gel_material: "optical_grease", - -dynode_radius: 27.5, // mm -dynode_top: -5.9, // mm -wall_thickness: 3.0, // mm - -z_edge: [ 96.7, 40.0, 0.0, -40.0, -90.0, -142.0 ], -rho_edge: [ 0.0, 111.0, 126.5, 111.0, 42.25, 42.25 ], -z_origin: [ -40.0, 0.0, 0.0, 40.0, -142.0 ], - -noise_rate: 10000.0, // Hz -} - - { name: "PMT", index: "r3600", From fab45634560ebec977f0abbc591fc9292da95063 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Tue, 3 Jun 2025 21:06:33 +0100 Subject: [PATCH 36/52] changes to encapsulation index and run_range --- ratdb/ENCAPSULATION.ratdb | 43 +++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/ratdb/ENCAPSULATION.ratdb b/ratdb/ENCAPSULATION.ratdb index a031c8a3..fb2d191e 100644 --- a/ratdb/ENCAPSULATION.ratdb +++ b/ratdb/ENCAPSULATION.ratdb @@ -1,31 +1,30 @@ { name: "ENCAPSULATION", -index : "BUTTON", -valid_begin : [ 0, 0 ], -valid_end : [ 0, 0 ], +index: "BUTTON_r7081pe", +run_range: [0, 0], construction: "hemisphere", -envelope_radius : 244.0, // should be large enough to fit all objects (>flange_rmax) -front_encapsulation_material : "nakano_acrylic", +envelope_radius: 244.0, // should be large enough to fit all objects (>flange_rmax) +front_encapsulation_material: "nakano_acrylic", rear_encapsulation_material: "acrylic_black", -flange_rmax : 243.0, // applies to acrylic and metal flange -encap_radius : 200.0, -encap_thickness : 8.0, -use_metal_flange : 1, -metal_flange_material : "stainless_steel", -metal_flange_dimensions : [ 220.0, 243.0, 4.0 ], // G4Tubs dimensions rmin, rmax, z -inside_encapsulation_material : "air", -use_optical_gel : 1, +flange_rmax: 243.0, // applies to acrylic and metal flange +encap_radius: 200.0, +encap_thickness: 8.0, +use_metal_flange: 1, +metal_flange_material: "stainless_steel", +metal_flange_dimensions: [ 220.0, 243.0, 4.0 ], // G4Tubs dimensions rmin, rmax, z +inside_encapsulation_material: "air", +use_optical_gel: 1, optical_gel_material: "optical_grease", -optical_gel_sub_height : 150.0, // start from a dome full of gel of size encap_radius, e.g. height of ... +optical_gel_sub_height: 150.0, // start from a dome full of gel of size encap_radius, e.g. height of ... // gel dome left is (encap_radius - optical_gel_sub_height) -pmtposoffset : [ 0.0, 0.0, 98.0 ], -use_silica_bag : 1, -silica_bag_material : "acrylic_white", -silica_bag_dimensions : [ 18.0, 33.0, 3.0 ], // G4Box dimensions x, y, z +pmtposoffset: [ 0.0, 0.0, 98.0 ], +use_silica_bag: 1, +silica_bag_material: "acrylic_white", +silica_bag_dimensions: [ 18.0, 33.0, 3.0 ], // G4Box dimensions x, y, z silica_bag_position: [ 0.0, 135.0, -74.0 ], // x, y, z -use_cable : 1, -cable_material : "acrylic_black", -cable_dimensions : [ 0.0, 6.5, 45.0 ], // G4Tubs dimensions rmin, rmax, z -cable_position : [ 0.0, 0.0, -152.0 ], // x, y, z +use_cable: 1, +cable_material: "acrylic_black", +cable_dimensions: [ 0.0, 6.5, 45.0 ], // G4Tubs dimensions rmin, rmax, z +cable_position: [ 0.0, 0.0, -152.0 ], // x, y, z } From 31c07db357407e9ff22c8ba1b51e6f88e32a89ad Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Wed, 4 Jun 2025 12:54:45 +0100 Subject: [PATCH 37/52] changed naming of pmtencapsulationconstruction to pmtencapsulation, moved inital description comment to header file --- src/geo/CMakeLists.txt | 2 +- src/geo/include/RAT/HemisphereEncapsulation.hh | 8 ++++++-- ...apsulationConstruction.hh => PMTEncapsulation.hh} | 12 ++++++------ src/geo/src/pmt/HemisphereEncapsulation.cc | 8 ++------ ...apsulationConstruction.cc => PMTEncapsulation.cc} | 4 ++-- src/geo/src/pmt/PMTFactoryBase.cc | 6 +++--- 6 files changed, 20 insertions(+), 20 deletions(-) rename src/geo/include/RAT/{PMTEncapsulationConstruction.hh => PMTEncapsulation.hh} (68%) rename src/geo/src/pmt/{PMTEncapsulationConstruction.cc => PMTEncapsulation.cc} (81%) diff --git a/src/geo/CMakeLists.txt b/src/geo/CMakeLists.txt index c1366ec2..b58becaa 100644 --- a/src/geo/CMakeLists.txt +++ b/src/geo/CMakeLists.txt @@ -64,7 +64,7 @@ add_library(geo OBJECT src/pmt/RevolutionPMTConstruction.cc src/pmt/ToroidalPMTConstruction.cc src/pmt/CylindricalPMTConstruction.cc - src/pmt/PMTEncapsulationConstruction.cc + src/pmt/PMTEncapsulation.cc src/pmt/HemisphereEncapsulation.cc ) diff --git a/src/geo/include/RAT/HemisphereEncapsulation.hh b/src/geo/include/RAT/HemisphereEncapsulation.hh index 01f20c7b..bc3c09bf 100644 --- a/src/geo/include/RAT/HemisphereEncapsulation.hh +++ b/src/geo/include/RAT/HemisphereEncapsulation.hh @@ -1,3 +1,7 @@ +// This is the encapsulation model that is used for BUTTON. +// The 96 Hamamatsu r7081pe PMTs are encapsulated by two acryilic domes that are held together with metal flanges. +// Created by Lewis Sexton (Sheffield) and Adam Tarrant (Liverpool) + #ifndef __RAT_HemisphereEncapsulation__ #define __RAT_HemisphereEncapsulation__ @@ -17,7 +21,7 @@ #include #include #include -#include +#include #include #include namespace RAT { @@ -67,7 +71,7 @@ struct HemisphereEncapsulationParams { G4OpticalSurface *optical_gel_surface; }; -class HemisphereEncapsulation : public PMTEncapsulationConstruction { +class HemisphereEncapsulation : public PMTEncapsulation { public: HemisphereEncapsulation(DBLinkPtr encaptable, DBLinkPtr pmttable, G4LogicalVolume *mother); virtual ~HemisphereEncapsulation() {} diff --git a/src/geo/include/RAT/PMTEncapsulationConstruction.hh b/src/geo/include/RAT/PMTEncapsulation.hh similarity index 68% rename from src/geo/include/RAT/PMTEncapsulationConstruction.hh rename to src/geo/include/RAT/PMTEncapsulation.hh index 760ba566..401b622e 100644 --- a/src/geo/include/RAT/PMTEncapsulationConstruction.hh +++ b/src/geo/include/RAT/PMTEncapsulation.hh @@ -1,5 +1,5 @@ -#ifndef __RAT_PMTEncapsulationConstruction__ -#define __RAT_PMTEncapsulationConstruction__ +#ifndef __RAT_PMTEncapsulation__ +#define __RAT_PMTEncapsulation__ #include #include @@ -10,14 +10,14 @@ namespace RAT { -class PMTEncapsulationConstruction { +class PMTEncapsulation { public: - static PMTEncapsulationConstruction *NewConstruction(DBLinkPtr encaptable, DBLinkPtr pmttable, + static PMTEncapsulation *NewConstruction(DBLinkPtr encaptable, DBLinkPtr pmttable, G4LogicalVolume *mother); - PMTEncapsulationConstruction(std::string _name) : name(_name) {} + PMTEncapsulation(std::string _name) : name(_name) {} - virtual ~PMTEncapsulationConstruction() {} + virtual ~PMTEncapsulation() {} virtual G4VSolid *BuildSolid(const std::string &prefix) = 0; diff --git a/src/geo/src/pmt/HemisphereEncapsulation.cc b/src/geo/src/pmt/HemisphereEncapsulation.cc index 1ff70497..e68682b9 100644 --- a/src/geo/src/pmt/HemisphereEncapsulation.cc +++ b/src/geo/src/pmt/HemisphereEncapsulation.cc @@ -1,7 +1,3 @@ -// This is the encapsulation that is used for BUTTON. -// The 96 Hamamatsu r7081pe PMTs are encapsulated by two acryilic domes that are held together with metal flanges. -// Created by Lewis Sexton (Sheffield) and Adam Tarrant (Liverpool) - #include #include @@ -19,13 +15,13 @@ #include #include #include -#include +#include #include namespace RAT { HemisphereEncapsulation::HemisphereEncapsulation(DBLinkPtr encaptable, DBLinkPtr pmttable, G4LogicalVolume *mother) - : PMTEncapsulationConstruction("hemisphere") { + : PMTEncapsulation("hemisphere") { inner_encapsulation_phys = 0; front_encapsulation_phys = 0; rear_encapsulation_phys = 0; diff --git a/src/geo/src/pmt/PMTEncapsulationConstruction.cc b/src/geo/src/pmt/PMTEncapsulation.cc similarity index 81% rename from src/geo/src/pmt/PMTEncapsulationConstruction.cc rename to src/geo/src/pmt/PMTEncapsulation.cc index f7d739c5..50ee83e9 100644 --- a/src/geo/src/pmt/PMTEncapsulationConstruction.cc +++ b/src/geo/src/pmt/PMTEncapsulation.cc @@ -7,12 +7,12 @@ #include #include #include -#include +#include #include namespace RAT { -PMTEncapsulationConstruction *PMTEncapsulationConstruction::NewConstruction(DBLinkPtr encaptable, DBLinkPtr pmttable, +PMTEncapsulation *PMTEncapsulation::NewConstruction(DBLinkPtr encaptable, DBLinkPtr pmttable, G4LogicalVolume *mother) { std::string construction = encaptable->Get("construction"); if (construction == "hemisphere") { diff --git a/src/geo/src/pmt/PMTFactoryBase.cc b/src/geo/src/pmt/PMTFactoryBase.cc index f38892dc..fb387d90 100644 --- a/src/geo/src/pmt/PMTFactoryBase.cc +++ b/src/geo/src/pmt/PMTFactoryBase.cc @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include @@ -46,7 +46,7 @@ G4VPhysicalVolume *PMTFactoryBase::ConstructPMTs( } G4ThreeVector local_offset = PMTInfoParser::ComputeLocalOffset(mother_name); - PMTEncapsulationConstruction *encap_construction = 0; + PMTEncapsulation *encap_construction = 0; G4LogicalVolume *log_encapenv = 0; PMTConstruction *construction = 0; G4LogicalVolume *log_pmt = 0; @@ -65,7 +65,7 @@ G4VPhysicalVolume *PMTFactoryBase::ConstructPMTs( info << "Encapsulation is turned on, using model: " << encapsulation_model << newline; - encap_construction = PMTEncapsulationConstruction::NewConstruction( + encap_construction = PMTEncapsulation::NewConstruction( lencapsulation, lpmt, mother); // make encapsulation, need to make/modify file log_encapenv = encap_construction->BuildVolume(volume_name); From eb8ccbc49152d6c3041cb475acb5adda151423e5 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Wed, 4 Jun 2025 12:56:32 +0100 Subject: [PATCH 38/52] changed naming of pmtencapsulationconstruction to pmtencapsulation, moved inital description comment to header file --- src/geo/include/RAT/PMTEncapsulation.hh | 3 +-- src/geo/src/pmt/PMTEncapsulation.cc | 3 +-- src/geo/src/pmt/PMTFactoryBase.cc | 4 ++-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/geo/include/RAT/PMTEncapsulation.hh b/src/geo/include/RAT/PMTEncapsulation.hh index 401b622e..340eef3c 100644 --- a/src/geo/include/RAT/PMTEncapsulation.hh +++ b/src/geo/include/RAT/PMTEncapsulation.hh @@ -12,8 +12,7 @@ namespace RAT { class PMTEncapsulation { public: - static PMTEncapsulation *NewConstruction(DBLinkPtr encaptable, DBLinkPtr pmttable, - G4LogicalVolume *mother); + static PMTEncapsulation *NewConstruction(DBLinkPtr encaptable, DBLinkPtr pmttable, G4LogicalVolume *mother); PMTEncapsulation(std::string _name) : name(_name) {} diff --git a/src/geo/src/pmt/PMTEncapsulation.cc b/src/geo/src/pmt/PMTEncapsulation.cc index 50ee83e9..f350d1e0 100644 --- a/src/geo/src/pmt/PMTEncapsulation.cc +++ b/src/geo/src/pmt/PMTEncapsulation.cc @@ -12,8 +12,7 @@ namespace RAT { -PMTEncapsulation *PMTEncapsulation::NewConstruction(DBLinkPtr encaptable, DBLinkPtr pmttable, - G4LogicalVolume *mother) { +PMTEncapsulation *PMTEncapsulation::NewConstruction(DBLinkPtr encaptable, DBLinkPtr pmttable, G4LogicalVolume *mother) { std::string construction = encaptable->Get("construction"); if (construction == "hemisphere") { return new HemisphereEncapsulation(encaptable, pmttable, mother); diff --git a/src/geo/src/pmt/PMTFactoryBase.cc b/src/geo/src/pmt/PMTFactoryBase.cc index fb387d90..3d1570f7 100644 --- a/src/geo/src/pmt/PMTFactoryBase.cc +++ b/src/geo/src/pmt/PMTFactoryBase.cc @@ -65,8 +65,8 @@ G4VPhysicalVolume *PMTFactoryBase::ConstructPMTs( info << "Encapsulation is turned on, using model: " << encapsulation_model << newline; - encap_construction = PMTEncapsulation::NewConstruction( - lencapsulation, lpmt, mother); // make encapsulation, need to make/modify file + encap_construction = PMTEncapsulation::NewConstruction(lencapsulation, lpmt, + mother); // make encapsulation, need to make/modify file log_encapenv = encap_construction->BuildVolume(volume_name); try { From efe4323450be34b5259c2ccca7b9adfcf9b56b49 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Wed, 4 Jun 2025 14:49:49 +0100 Subject: [PATCH 39/52] added optical gel check so that it can only be used if pmt construction is toroidal --- src/geo/src/pmt/HemisphereEncapsulation.cc | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/geo/src/pmt/HemisphereEncapsulation.cc b/src/geo/src/pmt/HemisphereEncapsulation.cc index e68682b9..8c8204f1 100644 --- a/src/geo/src/pmt/HemisphereEncapsulation.cc +++ b/src/geo/src/pmt/HemisphereEncapsulation.cc @@ -77,10 +77,21 @@ HemisphereEncapsulation::HemisphereEncapsulation(DBLinkPtr encaptable, DBLinkPtr // PMT is only needed if optical gel is used fParams.useGel = 0; // default to no gel - try { - fParams.useGel = encaptable->GetI("use_optical_gel"); - } catch (DBNotFoundError &e) { - }; + std::string pmttype = pmttable->GetS("construction"); + + // Check if optical gel can be used, needs toroidal + if (pmttype == "toroidal"){ + info << "Optical gel can be used since PMT construction is toroidal" << newline; + try { + fParams.useGel = encaptable->GetI("use_optical_gel"); + } catch (DBNotFoundError &e) { + }; + } + else if (pmttype != "toroidal") { + info << "Optical gel currently requires a toroidal PMT model, setting useGel = 0" << newline; + fParams.useGel = 0; + } + if (fParams.useGel == 1) { optical_gel_encapsulation_phys = 0; From 36d8dd919227fd91b8c9189643dde429d3f27392 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Wed, 4 Jun 2025 16:16:53 +0100 Subject: [PATCH 40/52] clang formatting --- src/geo/src/pmt/HemisphereEncapsulation.cc | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/geo/src/pmt/HemisphereEncapsulation.cc b/src/geo/src/pmt/HemisphereEncapsulation.cc index 8c8204f1..8dd738e9 100644 --- a/src/geo/src/pmt/HemisphereEncapsulation.cc +++ b/src/geo/src/pmt/HemisphereEncapsulation.cc @@ -78,20 +78,19 @@ HemisphereEncapsulation::HemisphereEncapsulation(DBLinkPtr encaptable, DBLinkPtr // PMT is only needed if optical gel is used fParams.useGel = 0; // default to no gel std::string pmttype = pmttable->GetS("construction"); - - // Check if optical gel can be used, needs toroidal - if (pmttype == "toroidal"){ + + // Check if optical gel can be used, needs toroidal + if (pmttype == "toroidal") { info << "Optical gel can be used since PMT construction is toroidal" << newline; try { fParams.useGel = encaptable->GetI("use_optical_gel"); - } catch (DBNotFoundError &e) { + } catch (DBNotFoundError &e) { }; - } - else if (pmttype != "toroidal") { + } else if (pmttype != "toroidal") { info << "Optical gel currently requires a toroidal PMT model, setting useGel = 0" << newline; fParams.useGel = 0; } - + if (fParams.useGel == 1) { optical_gel_encapsulation_phys = 0; From ef1866973e8217b78005b09bcd45f8a0be3b6bbc Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Wed, 4 Jun 2025 17:11:28 +0100 Subject: [PATCH 41/52] updated nakano acrylic --- ratdb/OPTICS.ratdb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ratdb/OPTICS.ratdb b/ratdb/OPTICS.ratdb index 74c524f1..f4e7b9a7 100644 --- a/ratdb/OPTICS.ratdb +++ b/ratdb/OPTICS.ratdb @@ -652,7 +652,7 @@ name : "OPTICS", index : "nakano_acrylic", valid_begin: [0, 0], valid_end: [0, 0], - +// Values measured/used for both WATCHMAN and BUTTON experiements RINDEX_option: "wavelength", RINDEX_value1: [60.0, 200.0, 210.0, 220.0, 230.0, 240.0, 250.0, 260.0, 270.0, 280.0, 290.0, 300.0, 310.0, 320.0, 330.0, 340.0, 350.0, 360.0, 370.0, 380.0, 390.0, 400.0, 410.0, 420.0, 430.0, 440.0, 450.0, 460.0, 470.0, 480.0, 490.0, 500.0, 510.0, 520.0, 530.0, 540.0, 550.0, 560.0, 570.0, 580.0, 590.0, 600.0, 610.0, 620.0, 630.0, 640.0, 650.0, 660.0, 670.0, 680.0, 690.0, 700.0, 710.0, 720.0, 730.0, 740.0, 750.0, 760.0, 770.0, 780.0, 790.0, 800.0, ], RINDEX_value2: [1.597, 1.597, 1.584, 1.573, 1.564, 1.556, 1.550, 1.544, 1.539, 1.534, 1.531, 1.527, 1.524, 1.521, 1.519, 1.516, 1.514, 1.512, 1.510, 1.509, 1.507, 1.506, 1.505, 1.503, 1.502, 1.501, 1.500, 1.499, 1.499, 1.498, 1.497, 1.496, 1.496, 1.495, 1.494, 1.494, 1.493, 1.493, 1.492, 1.492, 1.491, 1.491, 1.490, 1.490, 1.490, 1.489, 1.489, 1.488, 1.488, 1.488, 1.488, 1.487, 1.487, 1.487, 1.486, 1.486, 1.486, 1.486, 1.485, 1.485, 1.485, 1.485, ], From 08b804c26f9da3f886c94e7695b0cb243202656b Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Thu, 5 Jun 2025 13:38:45 +0100 Subject: [PATCH 42/52] updated nakano acrylic --- ratdb/OPTICS.ratdb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ratdb/OPTICS.ratdb b/ratdb/OPTICS.ratdb index f4e7b9a7..0a6e9327 100644 --- a/ratdb/OPTICS.ratdb +++ b/ratdb/OPTICS.ratdb @@ -652,7 +652,8 @@ name : "OPTICS", index : "nakano_acrylic", valid_begin: [0, 0], valid_end: [0, 0], -// Values measured/used for both WATCHMAN and BUTTON experiements +// Unpublished values measured internally by the BUTTON collaboration. +// Reproduced here with permission from the BUTTON collaboration. RINDEX_option: "wavelength", RINDEX_value1: [60.0, 200.0, 210.0, 220.0, 230.0, 240.0, 250.0, 260.0, 270.0, 280.0, 290.0, 300.0, 310.0, 320.0, 330.0, 340.0, 350.0, 360.0, 370.0, 380.0, 390.0, 400.0, 410.0, 420.0, 430.0, 440.0, 450.0, 460.0, 470.0, 480.0, 490.0, 500.0, 510.0, 520.0, 530.0, 540.0, 550.0, 560.0, 570.0, 580.0, 590.0, 600.0, 610.0, 620.0, 630.0, 640.0, 650.0, 660.0, 670.0, 680.0, 690.0, 700.0, 710.0, 720.0, 730.0, 740.0, 750.0, 760.0, 770.0, 780.0, 790.0, 800.0, ], RINDEX_value2: [1.597, 1.597, 1.584, 1.573, 1.564, 1.556, 1.550, 1.544, 1.539, 1.534, 1.531, 1.527, 1.524, 1.521, 1.519, 1.516, 1.514, 1.512, 1.510, 1.509, 1.507, 1.506, 1.505, 1.503, 1.502, 1.501, 1.500, 1.499, 1.499, 1.498, 1.497, 1.496, 1.496, 1.495, 1.494, 1.494, 1.493, 1.493, 1.492, 1.492, 1.491, 1.491, 1.490, 1.490, 1.490, 1.489, 1.489, 1.488, 1.488, 1.488, 1.488, 1.487, 1.487, 1.487, 1.486, 1.486, 1.486, 1.486, 1.485, 1.485, 1.485, 1.485, ], From 5d3d95d92654a844dffdd2caa2bcff3b19671a62 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Thu, 5 Jun 2025 17:38:15 +0100 Subject: [PATCH 43/52] changed line 85 so that pmt index name (volume name variable line 32) is used --- src/geo/src/pmt/PMTFactoryBase.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/geo/src/pmt/PMTFactoryBase.cc b/src/geo/src/pmt/PMTFactoryBase.cc index 3d1570f7..c066faa3 100644 --- a/src/geo/src/pmt/PMTFactoryBase.cc +++ b/src/geo/src/pmt/PMTFactoryBase.cc @@ -82,7 +82,7 @@ G4VPhysicalVolume *PMTFactoryBase::ConstructPMTs( if (mother == 0) { Log::Die("PMTParser: Unable to find mother volume " + mother_name + " for " + volume_name); } - phys_mother_encap = FindPhysMother("inner_pmts_inner_volume_encapsulation_phys"); + phys_mother_encap = FindPhysMother(volume_name+"_inner_volume_encapsulation_phys"); if (phys_mother == 0) { Log::Die("PMTParser: PMT mother physical volume " + mother_name + " not found"); } From 40e2ac16570b248d9f066a1fa8fef77133c12aa5 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Thu, 5 Jun 2025 17:38:38 +0100 Subject: [PATCH 44/52] changed line 85 so that pmt index name (volume name variable line 32) is used --- src/geo/src/pmt/PMTFactoryBase.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/geo/src/pmt/PMTFactoryBase.cc b/src/geo/src/pmt/PMTFactoryBase.cc index c066faa3..9d683cdd 100644 --- a/src/geo/src/pmt/PMTFactoryBase.cc +++ b/src/geo/src/pmt/PMTFactoryBase.cc @@ -82,7 +82,7 @@ G4VPhysicalVolume *PMTFactoryBase::ConstructPMTs( if (mother == 0) { Log::Die("PMTParser: Unable to find mother volume " + mother_name + " for " + volume_name); } - phys_mother_encap = FindPhysMother(volume_name+"_inner_volume_encapsulation_phys"); + phys_mother_encap = FindPhysMother(volume_name + "_inner_volume_encapsulation_phys"); if (phys_mother == 0) { Log::Die("PMTParser: PMT mother physical volume " + mother_name + " not found"); } From 426fd4c3900e9fa17a2d9bedba05da5d54a4e7db Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Thu, 5 Jun 2025 17:47:23 +0100 Subject: [PATCH 45/52] pmt.rst readded to remove conflict --- doc/users_guide/pmt.rst | 145 +++++++++++++++++++++++++++++----------- 1 file changed, 105 insertions(+), 40 deletions(-) diff --git a/doc/users_guide/pmt.rst b/doc/users_guide/pmt.rst index 4772fe18..2577be19 100644 --- a/doc/users_guide/pmt.rst +++ b/doc/users_guide/pmt.rst @@ -1,25 +1,62 @@ +.. _photodetector_simulation: + +Photodetector Simulation +------------------------ + +Several different photodetectors are available in `ratpac-two`. + +---------------- + .. _pmt_simulation: -PMT Simulation --------------- +PMTs +==== + +`ratpac-two` uses a custom PMT simulation. + +For each photon that enters a PMT volume, there is a probability of creating a photoelectron (PE), which is equal to the product of the quantum efficiency, an efficiency correction factor, and an optical correction factor that accounts for the polarization and incidence angle of the photon (relative to the photocathode). The bulk of the code that calculates the optical correction factor and applies the overall efficiency can be found in ``src/physics/src/GLG4PMTOpticalModel.cc``. + +The quantum efficiency for each PMT is defined in ``OPTICS_Photocathode.ratdb`` and is specified for each PMT in ``PMT.ratdb`` using the index ``photocathode_surface``. The efficiency correction factor can be specified in two different ways. First, a field in ``PMT.ratdb`` called ``efficiency_correction`` can be set to scale the efficiency of all PMTs of the specified type. The value of this scaling defaults to one. Second, an array of correction factors, called ``efficiency_corr``, can be set in the ``PMTINFO.ratdb`` file for every individual PMT. This will scale the efficiency for each PMT separately. + +Once it has been determined that a photoelectron should be created for a PMT, it is added to the ``HitPMTCollection``. For each hit PMT, a ``DS::MCPMT`` object is created. The PMT may have detected more than one PE, in which case the ``DS::MCPhoton`` class (which can be accessed by the ``GetMCPhoton()`` method in the ``MCPMT`` class) keeps track of information for each ``MCPE``. + +The ``DS::PMT`` objects are created only after a trigger event has been issued (see DAQ documentation :ref:`daq_processors`) and can include effects from the ``DAQ`` and ``trigger``. Similarly, the ``DS::DigitPMT`` objects are created by the waveform analysis processors, which run over digitized waveforms, as described in :ref:`waveform_analysis`. + + +.. _pmt_geometries: + +Geometries +'''''''''' + +Describe the different PMT geometries. + +Toroidal +######## + +Describe the toroidal PMTs. + +Revolution +########## + +Describe the revolution PMTs. + +Cubic +##### + +Describe the cubic PMTs. -RAT uses a custom PMT simulation extracted from GLG4Sim. +Cylindrical +########### + +Describe the cylindrical PMTs. ---------------- .. _pmt_response: Charge and Time Response -```````````````````````` -Gsim checks the database for single photoelectron charge and transit time PDFs -automatically for PMT models that are added to the geometry. These PDFs are -stored in tables named ``PMTCHARGE`` and ``PMTTRANSIT`` respectively, where the -index corresponds to a ``pmt_model`` field used in ``GEO`` tables. These PDFs -are sampled whenever a photon is absorbed by the photocathode to create a -realistic Q/T response automatically for PMTs independent of any DAQ processor. -If no tables are defined for a ``pmt_model`` the time defaults to approximately -zero spread from photoelectron absorption time and the charge defaults to a -phenomenological model used by MiniCLEAN. +'''''''''''''''''''''''' +The PMT charge and time response is set in ``Gsim``, which checks the database for single photoelectron charge and transit time PDFs automatically for PMT models that are added to the geometry. These PDFs are stored in tables named ``PMTCHARGE`` and ``PMTTRANSIT`` respectively, where the index corresponds to a ``pmt_model`` field used in ``GEO`` tables. These PDFs are sampled whenever a photon is absorbed by the photocathode to create realistic charge and time response automatically for PMTs independent of any DAQ processor. If no tables are defined for a ``pmt_model`` the time defaults to approximately zero spread from photoelectron absorption time and the charge defaults to the model for the large-area Hamamatsu r11780 12-inch PMT (arbitrary choice). ``PMTCHARGE`` fields: * ``charge`` - "x" values of the charge PDF (arbitrary units) @@ -31,12 +68,14 @@ phenomenological model used by MiniCLEAN. * ``time`` - "x" values of the time PDF (nanoseconds) * ``time_prob`` - "y" values of the time PDF (will be normalized) +Note that this ``cable_delay`` is applied to every single PE and can be used to shift the timing for all hits by a single value. This is separate from the per-PMT cable delays that can be applied, as described in :ref:`channel_status`. + ---------------- .. _dark_noise: -Dark Noise -`````````` +Dark Noise Processor +'''''''''''''''''''' PMTs have an intrinsic noise rate, or "dark current", which results from thermal excitation at the single electron level. These thermal electrons can exactly mimic a photoelectron from the PMT's photocathode and, thus, noise hits cannot be distinguished from 'true' hits caused by incident photons. The dark-noise simulation is performed by the ``NoiseProc`` processor, with controllable parameters set in the ``NoiseProc.ratdb`` table. @@ -45,7 +84,7 @@ The noise is included in the simulation after the physics event has been propaga .. _noise_control: Control -''''''' +####### The ``noise_flag`` in the ``NoiseProc.ratdb`` table sets the way in which the dark noise is simulated. 0: Global rate -- all PMTs in the detector have the same dark-rate. The value of the global rate is set by the ``default_noise_rate`` parameter. The default behavior of the noise processor is to use this global setting with a default rate of 1 kHz. @@ -86,10 +125,11 @@ Parameters:: * [values] doubles - sets the relevant parameters for the noise window, described further below. -.. _pmt_timing_and_charge: +.. _noise_timing_and_charge: Timing and charge distributions -''''''''''''''''''''''''''''''' +############################### + Noise hits are generated uniformly in time, throughout a window defined by the ``noise_lookback`` and ``noise_lookforward`` parameters in the ``NoiseProc.ratdb`` table. The parameters are set by default to 1000 ns each, and are typically centered around the first true PMT hit-time in the event (in the case that there are no hits, the window is centered around zero). The value of ``noise_maxtime`` sets the timing cut-off for generating noise-hits in the case of long-lived particles in the MC. The PMT charge distribution is sampled assuming the normal SPE charge distribution, as described in :ref:`pmt_response`. @@ -98,8 +138,8 @@ The PMT charge distribution is sampled assuming the normal SPE charge distributi .. _pmt_afterpulsing: -PMT Afterpulsing -```````````````` +PMT Afterpulsing Processor +'''''''''''''''''''''''''' Details of PMT afterpulsing @@ -108,23 +148,14 @@ Details of PMT afterpulsing .. _pmt_pulse: PMT Pulse Generation -```````````````````` +'''''''''''''''''''' Details of the PMT pulse generation here. ---------------- -.. _channel_status: - -Channel Status -`````````````` - -Details of the channel status here. - ----------------- - PMT Encapsulation -````````````````` +''''''''''''''''' PMT encapsulation is used for several reasons, such as to ensure compatibility with multiple detection media (e.g. air, water, doped water). @@ -135,7 +166,7 @@ The encapsulation code structure is based off the PMT construction structure, in When enabled, the encapsulation object is created first, followed the pmt object. The PMT is then placed inside the encapsulation before itself is placed in the mother volume given. Enabling Encapsulation -'''''''''''''''''''''' +###################### Encapsulation by default is turned off. In a .geo file, it can be enabled by adding the following line inside the ``inner_pmts`` index entry: :: @@ -153,9 +184,9 @@ The other line that must be included inside the ``inner_pmts`` index entry is th Where "modelname" must match an index entry name in ``ENCAPSULATION.ratdb``. Encapsulation model information -''''''''''''''''''''''''''''''' -Encapsulation models need to be added to ``ENCAPSULATION.ratdb``, which is loacted in ``ratpac/ratdb``. -A entry can be called by using the ``encapsulation_model:`` command as mentioned above. +############################### +Encapsulation models need to be added to ``ENCAPSULATION.ratdb``, which is located in ``ratpac/ratdb``. +An entry can be called by using the ``encapsulation_model:`` command as mentioned above. Each entry provides all the important information that is needed to create the encapsulation objects: * Construction type @@ -169,7 +200,7 @@ Any values given such as dimensions and positions should be given in mm. Multiple entries can use the same construction type, but can vary on the objects and object properties used. Adding a new Encapsulation construction -''''''''''''''''''''''''''''''''''''''' +####################################### Initially, the only encapsulation construction is the "hemisphere" type, which encapsulates the PMT inside two hemispheres. An inner volume is then created in which the PMT can be placed. @@ -187,14 +218,48 @@ This file uses the construction type that is given in the called ``ENCAPSULATION For a working example please see ``HemisphereEncapsulation.cc/hh`` which uses the "hemisphere" construction type. Placing PMT -''''''''''' +########### If encapsulation is used, then is possible that the medium inside the encapsulation is different to the mother volume medium it would be placed in without encapsulation on. -This can be change in ``PMTFactoryBase.cc`` to ensure that the correct mother volume is used for the placement. If using the visualizer, the scene tree is useful to see if the PMT has been placed inside the correct volume. +This can be changed in ``PMTFactoryBase.cc`` to ensure that the correct mother volume is used for the placement. If using the visualizer, the scene tree is useful to see if the PMT has been placed inside the correct volume. PMT Offset -'''''''''' +########## The encapsulation is placed using the PMT position(s) and direction(s) given, this means that by default the PMT is placed in the center of the encapsulation. An offset can be given in the ``ENCAPSULATION.ratdb`` entry so that the PMT is placed off-centre inside the encapsulation. This currently works for z-axis offsets (i.e move the PMT forwards/backwards). ----------------- \ No newline at end of file +---------------- + +PMT Concentrators +''''''''''''''''' + +Document the PMT concentrators. + +---------------- + +Magnetic Compensation +''''''''''''''''''''' + +Technically there is code in ``geo/src/pmt/PMTFactoryBase.cc`` that can be enabled to attempt to change the PMT efficiency based on a specified external magnetic field; however, this is not supported code and is by default turned off. + +LAPPDs +====== + +Describe LAPPDs here. + +---------------- + +Optical Fibers +============== + +Describe Liquid-O style fiber simulations here. + +---------------- + +.. _channel_status: + +Channel Status +============== + +Details of the channel status here. + From 6c54d2287ed6a6649345c446f3274a8bb4392e31 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Thu, 5 Jun 2025 19:12:22 +0100 Subject: [PATCH 46/52] removed pmt.rst --- doc/users_guide/pmt.rst | 265 ---------------------------------------- 1 file changed, 265 deletions(-) delete mode 100644 doc/users_guide/pmt.rst diff --git a/doc/users_guide/pmt.rst b/doc/users_guide/pmt.rst deleted file mode 100644 index 2577be19..00000000 --- a/doc/users_guide/pmt.rst +++ /dev/null @@ -1,265 +0,0 @@ -.. _photodetector_simulation: - -Photodetector Simulation ------------------------- - -Several different photodetectors are available in `ratpac-two`. - ----------------- - -.. _pmt_simulation: - -PMTs -==== - -`ratpac-two` uses a custom PMT simulation. - -For each photon that enters a PMT volume, there is a probability of creating a photoelectron (PE), which is equal to the product of the quantum efficiency, an efficiency correction factor, and an optical correction factor that accounts for the polarization and incidence angle of the photon (relative to the photocathode). The bulk of the code that calculates the optical correction factor and applies the overall efficiency can be found in ``src/physics/src/GLG4PMTOpticalModel.cc``. - -The quantum efficiency for each PMT is defined in ``OPTICS_Photocathode.ratdb`` and is specified for each PMT in ``PMT.ratdb`` using the index ``photocathode_surface``. The efficiency correction factor can be specified in two different ways. First, a field in ``PMT.ratdb`` called ``efficiency_correction`` can be set to scale the efficiency of all PMTs of the specified type. The value of this scaling defaults to one. Second, an array of correction factors, called ``efficiency_corr``, can be set in the ``PMTINFO.ratdb`` file for every individual PMT. This will scale the efficiency for each PMT separately. - -Once it has been determined that a photoelectron should be created for a PMT, it is added to the ``HitPMTCollection``. For each hit PMT, a ``DS::MCPMT`` object is created. The PMT may have detected more than one PE, in which case the ``DS::MCPhoton`` class (which can be accessed by the ``GetMCPhoton()`` method in the ``MCPMT`` class) keeps track of information for each ``MCPE``. - -The ``DS::PMT`` objects are created only after a trigger event has been issued (see DAQ documentation :ref:`daq_processors`) and can include effects from the ``DAQ`` and ``trigger``. Similarly, the ``DS::DigitPMT`` objects are created by the waveform analysis processors, which run over digitized waveforms, as described in :ref:`waveform_analysis`. - - -.. _pmt_geometries: - -Geometries -'''''''''' - -Describe the different PMT geometries. - -Toroidal -######## - -Describe the toroidal PMTs. - -Revolution -########## - -Describe the revolution PMTs. - -Cubic -##### - -Describe the cubic PMTs. - -Cylindrical -########### - -Describe the cylindrical PMTs. - ----------------- - -.. _pmt_response: - -Charge and Time Response -'''''''''''''''''''''''' -The PMT charge and time response is set in ``Gsim``, which checks the database for single photoelectron charge and transit time PDFs automatically for PMT models that are added to the geometry. These PDFs are stored in tables named ``PMTCHARGE`` and ``PMTTRANSIT`` respectively, where the index corresponds to a ``pmt_model`` field used in ``GEO`` tables. These PDFs are sampled whenever a photon is absorbed by the photocathode to create realistic charge and time response automatically for PMTs independent of any DAQ processor. If no tables are defined for a ``pmt_model`` the time defaults to approximately zero spread from photoelectron absorption time and the charge defaults to the model for the large-area Hamamatsu r11780 12-inch PMT (arbitrary choice). - -``PMTCHARGE`` fields: - * ``charge`` - "x" values of the charge PDF (arbitrary units) - * ``charge_prob`` - "y" values of the charge PDF (will be normalized) - - -``PMTTRANSIT`` fields: - * ``cable_delay`` - constant offset applied to all PMTs of this model (nanoseconds) - * ``time`` - "x" values of the time PDF (nanoseconds) - * ``time_prob`` - "y" values of the time PDF (will be normalized) - -Note that this ``cable_delay`` is applied to every single PE and can be used to shift the timing for all hits by a single value. This is separate from the per-PMT cable delays that can be applied, as described in :ref:`channel_status`. - ----------------- - -.. _dark_noise: - -Dark Noise Processor -'''''''''''''''''''' - -PMTs have an intrinsic noise rate, or "dark current", which results from thermal excitation at the single electron level. These thermal electrons can exactly mimic a photoelectron from the PMT's photocathode and, thus, noise hits cannot be distinguished from 'true' hits caused by incident photons. The dark-noise simulation is performed by the ``NoiseProc`` processor, with controllable parameters set in the ``NoiseProc.ratdb`` table. - -The noise is included in the simulation after the physics event has been propagated (all particles followed to extinction, and PMT hits recorded). In order to include the PMT noise hits into the trigger simulation, the noise processor should be called prior to the DAQ processor. All noise hits are flagged and can be selected using the ``isDarkHit`` method in the ``MCPhoton`` class. - -.. _noise_control: - -Control -####### -The ``noise_flag`` in the ``NoiseProc.ratdb`` table sets the way in which the dark noise is simulated. - -0: Global rate -- all PMTs in the detector have the same dark-rate. The value of the global rate is set by the ``default_noise_rate`` parameter. The default behavior of the noise processor is to use this global setting with a default rate of 1 kHz. - -1: Per PMT model rate -- all PMTs of the same type have the same rate. This may be useful if the detector has different types of PMTs. In this case the noise rate is read from the ``PMT.ratdb`` table for the appropriate model. - -2: Per PMT rate -- every PMT in the detector have a different noise rate. This may be useful if the noise rates have been measured for every PMT and one wants to simulate these specific per-PMT rates. In this case the noise rates are read from the relevant ``PMTINFO.ratdb`` file, where an array called ``noise_rate`` can be defined. As an example, from the macro we can change the noise simulation to per PMT-model rates and change the rate for a specified model:: - - /rat/db/set NOISEPROC noise_flag 1 - /rat/db/set PMT[r14688] noise_rate 5000.0 - -These parameters can also be set using ``procset``. For example, to set the ``default_noise_rate`` we would do:: - -/rat/proc noise -/rat/procset rate 5000.0 - -Command:: - -/rat/proc noise - -Parameters:: - -/rat/procset flag [value] - -* [value] int - sets the value of the ``noise_flag``. - -:: - -/rat/procset rate [value] - -* [value] double - sets the value of the ``default_noise_rate``. - -:: - -/rat/procset lookback [value] -/rat/procset lookforward [value] -/rat/procset maxtime [value] - -* [values] doubles - sets the relevant parameters for the noise window, described further below. - -.. _noise_timing_and_charge: - -Timing and charge distributions -############################### - -Noise hits are generated uniformly in time, throughout a window defined by the ``noise_lookback`` and ``noise_lookforward`` parameters in the ``NoiseProc.ratdb`` table. The parameters are set by default to 1000 ns each, and are typically centered around the first true PMT hit-time in the event (in the case that there are no hits, the window is centered around zero). The value of ``noise_maxtime`` sets the timing cut-off for generating noise-hits in the case of long-lived particles in the MC. - -The PMT charge distribution is sampled assuming the normal SPE charge distribution, as described in :ref:`pmt_response`. - ----------------- - -.. _pmt_afterpulsing: - -PMT Afterpulsing Processor -'''''''''''''''''''''''''' - -Details of PMT afterpulsing - ----------------- - -.. _pmt_pulse: - -PMT Pulse Generation -'''''''''''''''''''' - -Details of the PMT pulse generation here. - ----------------- - -PMT Encapsulation -''''''''''''''''' - -PMT encapsulation is used for several reasons, such as to ensure compatibility with multiple detection media (e.g. air, water, doped water). - -The encapsulation code was originally created for the BUTTON experiment, in which each of the 96 PMTs used are enclosed by two hemisphere domes that are sealed together by metal flanges and bolts. - -The encapsulation code structure is based off the PMT construction structure, in which a instance is initialized depending on the construction type given. - -When enabled, the encapsulation object is created first, followed the pmt object. The PMT is then placed inside the encapsulation before itself is placed in the mother volume given. - -Enabling Encapsulation -###################### -Encapsulation by default is turned off. -In a .geo file, it can be enabled by adding the following line inside the ``inner_pmts`` index entry: :: - - encapsulation: 1, - -With 0 being off. -It can also be added in a macro with: :: - - /rat/db/set GEO[inner_pmts] encapsulation 1 - -The other line that must be included inside the ``inner_pmts`` index entry is the model type: :: - - encapsulation_model: "modelname", - -Where "modelname" must match an index entry name in ``ENCAPSULATION.ratdb``. - -Encapsulation model information -############################### -Encapsulation models need to be added to ``ENCAPSULATION.ratdb``, which is located in ``ratpac/ratdb``. -An entry can be called by using the ``encapsulation_model:`` command as mentioned above. -Each entry provides all the important information that is needed to create the encapsulation objects: - -* Construction type -* Enable and disable additional objects -* Object dimensions and materials -* Off-centre object placements - -The construction type is needed to ensure the correct encapsulation construction is loaded. This represents the general shape of the encapsulation used. -For any materials used, their properties should be defined in ``MATERIALS.ratdb`` and ``OPTICS.ratdb``. -Any values given such as dimensions and positions should be given in mm. -Multiple entries can use the same construction type, but can vary on the objects and object properties used. - -Adding a new Encapsulation construction -####################################### -Initially, the only encapsulation construction is the "hemisphere" type, which encapsulates the PMT inside two hemispheres. -An inner volume is then created in which the PMT can be placed. - -When creating a new construction model (e.g. a box), the .cc file should contain three main functions: - -* An initial function that is called to create an instance with the information from the given ``ENCAPSULATION.ratdb`` entry. -* A build function that creates and returns the encapsulation. -* A placement function. - -A new encapsulation construction should make the build as customisable as possible. -The important object information such as those stated above should be called from an ``ENCAPSULATION.ratdb`` entry. - -To use a new construction type, the option must be added to ``PMTEncapsulationConstruction.cc``. -This file uses the construction type that is given in the called ``ENCAPSULATION.ratdb`` entry to initiate the associated encapsulation construction. -For a working example please see ``HemisphereEncapsulation.cc/hh`` which uses the "hemisphere" construction type. - -Placing PMT -########### -If encapsulation is used, then is possible that the medium inside the encapsulation is different to the mother volume medium it would be placed in without encapsulation on. -This can be changed in ``PMTFactoryBase.cc`` to ensure that the correct mother volume is used for the placement. If using the visualizer, the scene tree is useful to see if the PMT has been placed inside the correct volume. - - -PMT Offset -########## -The encapsulation is placed using the PMT position(s) and direction(s) given, this means that by default the PMT is placed in the center of the encapsulation. -An offset can be given in the ``ENCAPSULATION.ratdb`` entry so that the PMT is placed off-centre inside the encapsulation. This currently works for z-axis offsets (i.e move the PMT forwards/backwards). - ----------------- - -PMT Concentrators -''''''''''''''''' - -Document the PMT concentrators. - ----------------- - -Magnetic Compensation -''''''''''''''''''''' - -Technically there is code in ``geo/src/pmt/PMTFactoryBase.cc`` that can be enabled to attempt to change the PMT efficiency based on a specified external magnetic field; however, this is not supported code and is by default turned off. - -LAPPDs -====== - -Describe LAPPDs here. - ----------------- - -Optical Fibers -============== - -Describe Liquid-O style fiber simulations here. - ----------------- - -.. _channel_status: - -Channel Status -============== - -Details of the channel status here. - From edef2128ce9f2b145e1a71c17c5ca725c3791107 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Thu, 5 Jun 2025 19:17:04 +0100 Subject: [PATCH 47/52] old pmt.rst, should show no changes in diff --- doc/users_guide/pmt.rst | 200 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 doc/users_guide/pmt.rst diff --git a/doc/users_guide/pmt.rst b/doc/users_guide/pmt.rst new file mode 100644 index 00000000..6be4e13e --- /dev/null +++ b/doc/users_guide/pmt.rst @@ -0,0 +1,200 @@ +.. _pmt_simulation: + +PMT Simulation +-------------- + +RAT uses a custom PMT simulation extracted from GLG4Sim. + +---------------- + +.. _pmt_response: + +Charge and Time Response +```````````````````````` +Gsim checks the database for single photoelectron charge and transit time PDFs +automatically for PMT models that are added to the geometry. These PDFs are +stored in tables named ``PMTCHARGE`` and ``PMTTRANSIT`` respectively, where the +index corresponds to a ``pmt_model`` field used in ``GEO`` tables. These PDFs +are sampled whenever a photon is absorbed by the photocathode to create a +realistic Q/T response automatically for PMTs independent of any DAQ processor. +If no tables are defined for a ``pmt_model`` the time defaults to approximately +zero spread from photoelectron absorption time and the charge defaults to a +phenomenological model used by MiniCLEAN. + +``PMTCHARGE`` fields: + * ``charge`` - "x" values of the charge PDF (arbitrary units) + * ``charge_prob`` - "y" values of the charge PDF (will be normalized) + + +``PMTTRANSIT`` fields: + * ``cable_delay`` - constant offset applied to all PMTs of this model (nanoseconds) + * ``time`` - "x" values of the time PDF (nanoseconds) + * ``time_prob`` - "y" values of the time PDF (will be normalized) + +---------------- + +.. _dark_noise: + +Dark Noise +`````````` + +PMTs have an intrinsic noise rate, or "dark current", which results from thermal excitation at the single electron level. These thermal electrons can exactly mimic a photoelectron from the PMT's photocathode and, thus, noise hits cannot be distinguished from 'true' hits caused by incident photons. The dark-noise simulation is performed by the ``NoiseProc`` processor, with controllable parameters set in the ``NoiseProc.ratdb`` table. + +The noise is included in the simulation after the physics event has been propagated (all particles followed to extinction, and PMT hits recorded). In order to include the PMT noise hits into the trigger simulation, the noise processor should be called prior to the DAQ processor. All noise hits are flagged and can be selected using the ``isDarkHit`` method in the ``MCPhoton`` class. + +.. _noise_control: + +Control +''''''' +The ``noise_flag`` in the ``NoiseProc.ratdb`` table sets the way in which the dark noise is simulated. + +0: Global rate -- all PMTs in the detector have the same dark-rate. The value of the global rate is set by the ``default_noise_rate`` parameter. The default behavior of the noise processor is to use this global setting with a default rate of 1 kHz. + +1: Per PMT model rate -- all PMTs of the same type have the same rate. This may be useful if the detector has different types of PMTs. In this case the noise rate is read from the ``PMT.ratdb`` table for the appropriate model. + +2: Per PMT rate -- every PMT in the detector have a different noise rate. This may be useful if the noise rates have been measured for every PMT and one wants to simulate these specific per-PMT rates. In this case the noise rates are read from the relevant ``PMTINFO.ratdb`` file, where an array called ``noise_rate`` can be defined. As an example, from the macro we can change the noise simulation to per PMT-model rates and change the rate for a specified model:: + + /rat/db/set NOISEPROC noise_flag 1 + /rat/db/set PMT[r14688] noise_rate 5000.0 + +These parameters can also be set using ``procset``. For example, to set the ``default_noise_rate`` we would do:: + +/rat/proc noise +/rat/procset rate 5000.0 + +Command:: + +/rat/proc noise + +Parameters:: + +/rat/procset flag [value] + +* [value] int - sets the value of the ``noise_flag``. + +:: + +/rat/procset rate [value] + +* [value] double - sets the value of the ``default_noise_rate``. + +:: + +/rat/procset lookback [value] +/rat/procset lookforward [value] +/rat/procset maxtime [value] + +* [values] doubles - sets the relevant parameters for the noise window, described further below. + +.. _pmt_timing_and_charge: + +Timing and charge distributions +''''''''''''''''''''''''''''''' +Noise hits are generated uniformly in time, throughout a window defined by the ``noise_lookback`` and ``noise_lookforward`` parameters in the ``NoiseProc.ratdb`` table. The parameters are set by default to 1000 ns each, and are typically centered around the first true PMT hit-time in the event (in the case that there are no hits, the window is centered around zero). The value of ``noise_maxtime`` sets the timing cut-off for generating noise-hits in the case of long-lived particles in the MC. + +The PMT charge distribution is sampled assuming the normal SPE charge distribution, as described in :ref:`pmt_response`. + +---------------- + +.. _pmt_afterpulsing: + +PMT Afterpulsing +```````````````` + +Details of PMT afterpulsing + +---------------- + +.. _pmt_pulse: + +PMT Pulse Generation +```````````````````` + +Details of the PMT pulse generation here. + +---------------- + +.. _channel_status: + +Channel Status +`````````````` + +Details of the channel status here. + +---------------- + +PMT Encapsulation +````````````````` + +PMT encapsulation is used for several reasons, such as to ensure compatibility with multiple detection media (e.g. air, water, doped water). + +The encapsulation code was originally created for the BUTTON experiment, in which each of the 96 PMTs used are enclosed by two hemisphere domes that are sealed together by metal flanges and bolts. + +The encapsulation code structure is based off the PMT construction structure, in which a instance is initialized depending on the construction type given. + +When enabled, the encapsulation object is created first, followed the pmt object. The PMT is then placed inside the encapsulation before itself is placed in the mother volume given. + +Enabling Encapsulation +'''''''''''''''''''''' +Encapsulation by default is turned off. +In a .geo file, it can be enabled by adding the following line inside the ``inner_pmts`` index entry: :: + + encapsulation: 1, + +With 0 being off. +It can also be added in a macro with: :: + + /rat/db/set GEO[inner_pmts] encapsulation 1 + +The other line that must be included inside the ``inner_pmts`` index entry is the model type: :: + + encapsulation_model: "modelname", + +Where "modelname" must match an index entry name in ``ENCAPSULATION.ratdb``. + +Encapsulation model information +''''''''''''''''''''''''''''''' +Encapsulation models need to be added to ``ENCAPSULATION.ratdb``, which is loacted in ``ratpac/ratdb``. +A entry can be called by using the ``encapsulation_model:`` command as mentioned above. +Each entry provides all the important information that is needed to create the encapsulation objects: + +* Construction type +* Enable and disable additional objects +* Object dimensions and materials +* Off-centre object placements + +The construction type is needed to ensure the correct encapsulation construction is loaded. This represents the general shape of the encapsulation used. +For any materials used, their properties should be defined in ``MATERIALS.ratdb`` and ``OPTICS.ratdb``. +Any values given such as dimensions and positions should be given in mm. +Multiple entries can use the same construction type, but can vary on the objects and object properties used. + +Adding a new Encapsulation construction +''''''''''''''''''''''''''''''''''''''' +Initially, the only encapsulation construction is the "hemisphere" type, which encapsulates the PMT inside two hemispheres. +An inner volume is then created in which the PMT can be placed. + +When creating a new construction model (e.g. a box), the .cc file should contain three main functions: + +* An initial function that is called to create an instance with the information from the given ``ENCAPSULATION.ratdb`` entry. +* A build function that creates and returns the encapsulation. +* A placement function. + +A new encapsulation construction should make the build as customisable as possible. +The important object information such as those stated above should be called from an ``ENCAPSULATION.ratdb`` entry. + +To use a new construction type, the option must be added to ``PMTEncapsulationConstruction.cc``. +This file uses the construction type that is given in the called ``ENCAPSULATION.ratdb`` entry to initiate the associated encapsulation construction. +For a working example please see ``HemisphereEncapsulation.cc/hh`` which uses the "hemisphere" construction type. + +Placing PMT +''''''''''' +If encapsulation is used, then is possible that the medium inside the encapsulation is different to the mother volume medium it would be placed in without encapsulation on. +This can be change in ``PMTFactoryBase.cc`` to ensure that the correct mother volume is used for the placement. If using the visualizer, the scene tree is useful to see if the PMT has been placed inside the correct volume. + + +PMT Offset +'''''''''' +The encapsulation is placed using the PMT position(s) and direction(s) given, this means that by default the PMT is placed in the center of the encapsulation. +An offset can be given in the ``ENCAPSULATION.ratdb`` entry so that the PMT is placed off-centre inside the encapsulation. This currently works for z-axis offsets (i.e move the PMT forwards/backwards). + +---------------- From f96c7f2eb642ec7ff44362c678c759c478b3952b Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Thu, 5 Jun 2025 19:19:48 +0100 Subject: [PATCH 48/52] up to date pmt.rst --- doc/users_guide/pmt.rst | 465 +++++++++++++++++++++++----------------- 1 file changed, 265 insertions(+), 200 deletions(-) diff --git a/doc/users_guide/pmt.rst b/doc/users_guide/pmt.rst index 6be4e13e..2577be19 100644 --- a/doc/users_guide/pmt.rst +++ b/doc/users_guide/pmt.rst @@ -1,200 +1,265 @@ -.. _pmt_simulation: - -PMT Simulation --------------- - -RAT uses a custom PMT simulation extracted from GLG4Sim. - ----------------- - -.. _pmt_response: - -Charge and Time Response -```````````````````````` -Gsim checks the database for single photoelectron charge and transit time PDFs -automatically for PMT models that are added to the geometry. These PDFs are -stored in tables named ``PMTCHARGE`` and ``PMTTRANSIT`` respectively, where the -index corresponds to a ``pmt_model`` field used in ``GEO`` tables. These PDFs -are sampled whenever a photon is absorbed by the photocathode to create a -realistic Q/T response automatically for PMTs independent of any DAQ processor. -If no tables are defined for a ``pmt_model`` the time defaults to approximately -zero spread from photoelectron absorption time and the charge defaults to a -phenomenological model used by MiniCLEAN. - -``PMTCHARGE`` fields: - * ``charge`` - "x" values of the charge PDF (arbitrary units) - * ``charge_prob`` - "y" values of the charge PDF (will be normalized) - - -``PMTTRANSIT`` fields: - * ``cable_delay`` - constant offset applied to all PMTs of this model (nanoseconds) - * ``time`` - "x" values of the time PDF (nanoseconds) - * ``time_prob`` - "y" values of the time PDF (will be normalized) - ----------------- - -.. _dark_noise: - -Dark Noise -`````````` - -PMTs have an intrinsic noise rate, or "dark current", which results from thermal excitation at the single electron level. These thermal electrons can exactly mimic a photoelectron from the PMT's photocathode and, thus, noise hits cannot be distinguished from 'true' hits caused by incident photons. The dark-noise simulation is performed by the ``NoiseProc`` processor, with controllable parameters set in the ``NoiseProc.ratdb`` table. - -The noise is included in the simulation after the physics event has been propagated (all particles followed to extinction, and PMT hits recorded). In order to include the PMT noise hits into the trigger simulation, the noise processor should be called prior to the DAQ processor. All noise hits are flagged and can be selected using the ``isDarkHit`` method in the ``MCPhoton`` class. - -.. _noise_control: - -Control -''''''' -The ``noise_flag`` in the ``NoiseProc.ratdb`` table sets the way in which the dark noise is simulated. - -0: Global rate -- all PMTs in the detector have the same dark-rate. The value of the global rate is set by the ``default_noise_rate`` parameter. The default behavior of the noise processor is to use this global setting with a default rate of 1 kHz. - -1: Per PMT model rate -- all PMTs of the same type have the same rate. This may be useful if the detector has different types of PMTs. In this case the noise rate is read from the ``PMT.ratdb`` table for the appropriate model. - -2: Per PMT rate -- every PMT in the detector have a different noise rate. This may be useful if the noise rates have been measured for every PMT and one wants to simulate these specific per-PMT rates. In this case the noise rates are read from the relevant ``PMTINFO.ratdb`` file, where an array called ``noise_rate`` can be defined. As an example, from the macro we can change the noise simulation to per PMT-model rates and change the rate for a specified model:: - - /rat/db/set NOISEPROC noise_flag 1 - /rat/db/set PMT[r14688] noise_rate 5000.0 - -These parameters can also be set using ``procset``. For example, to set the ``default_noise_rate`` we would do:: - -/rat/proc noise -/rat/procset rate 5000.0 - -Command:: - -/rat/proc noise - -Parameters:: - -/rat/procset flag [value] - -* [value] int - sets the value of the ``noise_flag``. - -:: - -/rat/procset rate [value] - -* [value] double - sets the value of the ``default_noise_rate``. - -:: - -/rat/procset lookback [value] -/rat/procset lookforward [value] -/rat/procset maxtime [value] - -* [values] doubles - sets the relevant parameters for the noise window, described further below. - -.. _pmt_timing_and_charge: - -Timing and charge distributions -''''''''''''''''''''''''''''''' -Noise hits are generated uniformly in time, throughout a window defined by the ``noise_lookback`` and ``noise_lookforward`` parameters in the ``NoiseProc.ratdb`` table. The parameters are set by default to 1000 ns each, and are typically centered around the first true PMT hit-time in the event (in the case that there are no hits, the window is centered around zero). The value of ``noise_maxtime`` sets the timing cut-off for generating noise-hits in the case of long-lived particles in the MC. - -The PMT charge distribution is sampled assuming the normal SPE charge distribution, as described in :ref:`pmt_response`. - ----------------- - -.. _pmt_afterpulsing: - -PMT Afterpulsing -```````````````` - -Details of PMT afterpulsing - ----------------- - -.. _pmt_pulse: - -PMT Pulse Generation -```````````````````` - -Details of the PMT pulse generation here. - ----------------- - -.. _channel_status: - -Channel Status -`````````````` - -Details of the channel status here. - ----------------- - -PMT Encapsulation -````````````````` - -PMT encapsulation is used for several reasons, such as to ensure compatibility with multiple detection media (e.g. air, water, doped water). - -The encapsulation code was originally created for the BUTTON experiment, in which each of the 96 PMTs used are enclosed by two hemisphere domes that are sealed together by metal flanges and bolts. - -The encapsulation code structure is based off the PMT construction structure, in which a instance is initialized depending on the construction type given. - -When enabled, the encapsulation object is created first, followed the pmt object. The PMT is then placed inside the encapsulation before itself is placed in the mother volume given. - -Enabling Encapsulation -'''''''''''''''''''''' -Encapsulation by default is turned off. -In a .geo file, it can be enabled by adding the following line inside the ``inner_pmts`` index entry: :: - - encapsulation: 1, - -With 0 being off. -It can also be added in a macro with: :: - - /rat/db/set GEO[inner_pmts] encapsulation 1 - -The other line that must be included inside the ``inner_pmts`` index entry is the model type: :: - - encapsulation_model: "modelname", - -Where "modelname" must match an index entry name in ``ENCAPSULATION.ratdb``. - -Encapsulation model information -''''''''''''''''''''''''''''''' -Encapsulation models need to be added to ``ENCAPSULATION.ratdb``, which is loacted in ``ratpac/ratdb``. -A entry can be called by using the ``encapsulation_model:`` command as mentioned above. -Each entry provides all the important information that is needed to create the encapsulation objects: - -* Construction type -* Enable and disable additional objects -* Object dimensions and materials -* Off-centre object placements - -The construction type is needed to ensure the correct encapsulation construction is loaded. This represents the general shape of the encapsulation used. -For any materials used, their properties should be defined in ``MATERIALS.ratdb`` and ``OPTICS.ratdb``. -Any values given such as dimensions and positions should be given in mm. -Multiple entries can use the same construction type, but can vary on the objects and object properties used. - -Adding a new Encapsulation construction -''''''''''''''''''''''''''''''''''''''' -Initially, the only encapsulation construction is the "hemisphere" type, which encapsulates the PMT inside two hemispheres. -An inner volume is then created in which the PMT can be placed. - -When creating a new construction model (e.g. a box), the .cc file should contain three main functions: - -* An initial function that is called to create an instance with the information from the given ``ENCAPSULATION.ratdb`` entry. -* A build function that creates and returns the encapsulation. -* A placement function. - -A new encapsulation construction should make the build as customisable as possible. -The important object information such as those stated above should be called from an ``ENCAPSULATION.ratdb`` entry. - -To use a new construction type, the option must be added to ``PMTEncapsulationConstruction.cc``. -This file uses the construction type that is given in the called ``ENCAPSULATION.ratdb`` entry to initiate the associated encapsulation construction. -For a working example please see ``HemisphereEncapsulation.cc/hh`` which uses the "hemisphere" construction type. - -Placing PMT -''''''''''' -If encapsulation is used, then is possible that the medium inside the encapsulation is different to the mother volume medium it would be placed in without encapsulation on. -This can be change in ``PMTFactoryBase.cc`` to ensure that the correct mother volume is used for the placement. If using the visualizer, the scene tree is useful to see if the PMT has been placed inside the correct volume. - - -PMT Offset -'''''''''' -The encapsulation is placed using the PMT position(s) and direction(s) given, this means that by default the PMT is placed in the center of the encapsulation. -An offset can be given in the ``ENCAPSULATION.ratdb`` entry so that the PMT is placed off-centre inside the encapsulation. This currently works for z-axis offsets (i.e move the PMT forwards/backwards). - ----------------- +.. _photodetector_simulation: + +Photodetector Simulation +------------------------ + +Several different photodetectors are available in `ratpac-two`. + +---------------- + +.. _pmt_simulation: + +PMTs +==== + +`ratpac-two` uses a custom PMT simulation. + +For each photon that enters a PMT volume, there is a probability of creating a photoelectron (PE), which is equal to the product of the quantum efficiency, an efficiency correction factor, and an optical correction factor that accounts for the polarization and incidence angle of the photon (relative to the photocathode). The bulk of the code that calculates the optical correction factor and applies the overall efficiency can be found in ``src/physics/src/GLG4PMTOpticalModel.cc``. + +The quantum efficiency for each PMT is defined in ``OPTICS_Photocathode.ratdb`` and is specified for each PMT in ``PMT.ratdb`` using the index ``photocathode_surface``. The efficiency correction factor can be specified in two different ways. First, a field in ``PMT.ratdb`` called ``efficiency_correction`` can be set to scale the efficiency of all PMTs of the specified type. The value of this scaling defaults to one. Second, an array of correction factors, called ``efficiency_corr``, can be set in the ``PMTINFO.ratdb`` file for every individual PMT. This will scale the efficiency for each PMT separately. + +Once it has been determined that a photoelectron should be created for a PMT, it is added to the ``HitPMTCollection``. For each hit PMT, a ``DS::MCPMT`` object is created. The PMT may have detected more than one PE, in which case the ``DS::MCPhoton`` class (which can be accessed by the ``GetMCPhoton()`` method in the ``MCPMT`` class) keeps track of information for each ``MCPE``. + +The ``DS::PMT`` objects are created only after a trigger event has been issued (see DAQ documentation :ref:`daq_processors`) and can include effects from the ``DAQ`` and ``trigger``. Similarly, the ``DS::DigitPMT`` objects are created by the waveform analysis processors, which run over digitized waveforms, as described in :ref:`waveform_analysis`. + + +.. _pmt_geometries: + +Geometries +'''''''''' + +Describe the different PMT geometries. + +Toroidal +######## + +Describe the toroidal PMTs. + +Revolution +########## + +Describe the revolution PMTs. + +Cubic +##### + +Describe the cubic PMTs. + +Cylindrical +########### + +Describe the cylindrical PMTs. + +---------------- + +.. _pmt_response: + +Charge and Time Response +'''''''''''''''''''''''' +The PMT charge and time response is set in ``Gsim``, which checks the database for single photoelectron charge and transit time PDFs automatically for PMT models that are added to the geometry. These PDFs are stored in tables named ``PMTCHARGE`` and ``PMTTRANSIT`` respectively, where the index corresponds to a ``pmt_model`` field used in ``GEO`` tables. These PDFs are sampled whenever a photon is absorbed by the photocathode to create realistic charge and time response automatically for PMTs independent of any DAQ processor. If no tables are defined for a ``pmt_model`` the time defaults to approximately zero spread from photoelectron absorption time and the charge defaults to the model for the large-area Hamamatsu r11780 12-inch PMT (arbitrary choice). + +``PMTCHARGE`` fields: + * ``charge`` - "x" values of the charge PDF (arbitrary units) + * ``charge_prob`` - "y" values of the charge PDF (will be normalized) + + +``PMTTRANSIT`` fields: + * ``cable_delay`` - constant offset applied to all PMTs of this model (nanoseconds) + * ``time`` - "x" values of the time PDF (nanoseconds) + * ``time_prob`` - "y" values of the time PDF (will be normalized) + +Note that this ``cable_delay`` is applied to every single PE and can be used to shift the timing for all hits by a single value. This is separate from the per-PMT cable delays that can be applied, as described in :ref:`channel_status`. + +---------------- + +.. _dark_noise: + +Dark Noise Processor +'''''''''''''''''''' + +PMTs have an intrinsic noise rate, or "dark current", which results from thermal excitation at the single electron level. These thermal electrons can exactly mimic a photoelectron from the PMT's photocathode and, thus, noise hits cannot be distinguished from 'true' hits caused by incident photons. The dark-noise simulation is performed by the ``NoiseProc`` processor, with controllable parameters set in the ``NoiseProc.ratdb`` table. + +The noise is included in the simulation after the physics event has been propagated (all particles followed to extinction, and PMT hits recorded). In order to include the PMT noise hits into the trigger simulation, the noise processor should be called prior to the DAQ processor. All noise hits are flagged and can be selected using the ``isDarkHit`` method in the ``MCPhoton`` class. + +.. _noise_control: + +Control +####### +The ``noise_flag`` in the ``NoiseProc.ratdb`` table sets the way in which the dark noise is simulated. + +0: Global rate -- all PMTs in the detector have the same dark-rate. The value of the global rate is set by the ``default_noise_rate`` parameter. The default behavior of the noise processor is to use this global setting with a default rate of 1 kHz. + +1: Per PMT model rate -- all PMTs of the same type have the same rate. This may be useful if the detector has different types of PMTs. In this case the noise rate is read from the ``PMT.ratdb`` table for the appropriate model. + +2: Per PMT rate -- every PMT in the detector have a different noise rate. This may be useful if the noise rates have been measured for every PMT and one wants to simulate these specific per-PMT rates. In this case the noise rates are read from the relevant ``PMTINFO.ratdb`` file, where an array called ``noise_rate`` can be defined. As an example, from the macro we can change the noise simulation to per PMT-model rates and change the rate for a specified model:: + + /rat/db/set NOISEPROC noise_flag 1 + /rat/db/set PMT[r14688] noise_rate 5000.0 + +These parameters can also be set using ``procset``. For example, to set the ``default_noise_rate`` we would do:: + +/rat/proc noise +/rat/procset rate 5000.0 + +Command:: + +/rat/proc noise + +Parameters:: + +/rat/procset flag [value] + +* [value] int - sets the value of the ``noise_flag``. + +:: + +/rat/procset rate [value] + +* [value] double - sets the value of the ``default_noise_rate``. + +:: + +/rat/procset lookback [value] +/rat/procset lookforward [value] +/rat/procset maxtime [value] + +* [values] doubles - sets the relevant parameters for the noise window, described further below. + +.. _noise_timing_and_charge: + +Timing and charge distributions +############################### + +Noise hits are generated uniformly in time, throughout a window defined by the ``noise_lookback`` and ``noise_lookforward`` parameters in the ``NoiseProc.ratdb`` table. The parameters are set by default to 1000 ns each, and are typically centered around the first true PMT hit-time in the event (in the case that there are no hits, the window is centered around zero). The value of ``noise_maxtime`` sets the timing cut-off for generating noise-hits in the case of long-lived particles in the MC. + +The PMT charge distribution is sampled assuming the normal SPE charge distribution, as described in :ref:`pmt_response`. + +---------------- + +.. _pmt_afterpulsing: + +PMT Afterpulsing Processor +'''''''''''''''''''''''''' + +Details of PMT afterpulsing + +---------------- + +.. _pmt_pulse: + +PMT Pulse Generation +'''''''''''''''''''' + +Details of the PMT pulse generation here. + +---------------- + +PMT Encapsulation +''''''''''''''''' + +PMT encapsulation is used for several reasons, such as to ensure compatibility with multiple detection media (e.g. air, water, doped water). + +The encapsulation code was originally created for the BUTTON experiment, in which each of the 96 PMTs used are enclosed by two hemisphere domes that are sealed together by metal flanges and bolts. + +The encapsulation code structure is based off the PMT construction structure, in which a instance is initialized depending on the construction type given. + +When enabled, the encapsulation object is created first, followed the pmt object. The PMT is then placed inside the encapsulation before itself is placed in the mother volume given. + +Enabling Encapsulation +###################### +Encapsulation by default is turned off. +In a .geo file, it can be enabled by adding the following line inside the ``inner_pmts`` index entry: :: + + encapsulation: 1, + +With 0 being off. +It can also be added in a macro with: :: + + /rat/db/set GEO[inner_pmts] encapsulation 1 + +The other line that must be included inside the ``inner_pmts`` index entry is the model type: :: + + encapsulation_model: "modelname", + +Where "modelname" must match an index entry name in ``ENCAPSULATION.ratdb``. + +Encapsulation model information +############################### +Encapsulation models need to be added to ``ENCAPSULATION.ratdb``, which is located in ``ratpac/ratdb``. +An entry can be called by using the ``encapsulation_model:`` command as mentioned above. +Each entry provides all the important information that is needed to create the encapsulation objects: + +* Construction type +* Enable and disable additional objects +* Object dimensions and materials +* Off-centre object placements + +The construction type is needed to ensure the correct encapsulation construction is loaded. This represents the general shape of the encapsulation used. +For any materials used, their properties should be defined in ``MATERIALS.ratdb`` and ``OPTICS.ratdb``. +Any values given such as dimensions and positions should be given in mm. +Multiple entries can use the same construction type, but can vary on the objects and object properties used. + +Adding a new Encapsulation construction +####################################### +Initially, the only encapsulation construction is the "hemisphere" type, which encapsulates the PMT inside two hemispheres. +An inner volume is then created in which the PMT can be placed. + +When creating a new construction model (e.g. a box), the .cc file should contain three main functions: + +* An initial function that is called to create an instance with the information from the given ``ENCAPSULATION.ratdb`` entry. +* A build function that creates and returns the encapsulation. +* A placement function. + +A new encapsulation construction should make the build as customisable as possible. +The important object information such as those stated above should be called from an ``ENCAPSULATION.ratdb`` entry. + +To use a new construction type, the option must be added to ``PMTEncapsulationConstruction.cc``. +This file uses the construction type that is given in the called ``ENCAPSULATION.ratdb`` entry to initiate the associated encapsulation construction. +For a working example please see ``HemisphereEncapsulation.cc/hh`` which uses the "hemisphere" construction type. + +Placing PMT +########### +If encapsulation is used, then is possible that the medium inside the encapsulation is different to the mother volume medium it would be placed in without encapsulation on. +This can be changed in ``PMTFactoryBase.cc`` to ensure that the correct mother volume is used for the placement. If using the visualizer, the scene tree is useful to see if the PMT has been placed inside the correct volume. + + +PMT Offset +########## +The encapsulation is placed using the PMT position(s) and direction(s) given, this means that by default the PMT is placed in the center of the encapsulation. +An offset can be given in the ``ENCAPSULATION.ratdb`` entry so that the PMT is placed off-centre inside the encapsulation. This currently works for z-axis offsets (i.e move the PMT forwards/backwards). + +---------------- + +PMT Concentrators +''''''''''''''''' + +Document the PMT concentrators. + +---------------- + +Magnetic Compensation +''''''''''''''''''''' + +Technically there is code in ``geo/src/pmt/PMTFactoryBase.cc`` that can be enabled to attempt to change the PMT efficiency based on a specified external magnetic field; however, this is not supported code and is by default turned off. + +LAPPDs +====== + +Describe LAPPDs here. + +---------------- + +Optical Fibers +============== + +Describe Liquid-O style fiber simulations here. + +---------------- + +.. _channel_status: + +Channel Status +============== + +Details of the channel status here. + From be5c53b331e26ce6a343b2ba7c6080be316ad5be Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Thu, 5 Jun 2025 21:44:44 +0100 Subject: [PATCH 49/52] removed nakano acrylic, will use acrylic_uvt_good instead, and keep nakano for private repo --- ratdb/ENCAPSULATION.ratdb | 2 +- ratdb/MATERIALS.ratdb | 11 ----------- ratdb/OPTICS.ratdb | 18 ------------------ ratdb/Validation/WaterWorld.geo | 11 +++++++++++ 4 files changed, 12 insertions(+), 30 deletions(-) create mode 100644 ratdb/Validation/WaterWorld.geo diff --git a/ratdb/ENCAPSULATION.ratdb b/ratdb/ENCAPSULATION.ratdb index fb2d191e..3d860fc9 100644 --- a/ratdb/ENCAPSULATION.ratdb +++ b/ratdb/ENCAPSULATION.ratdb @@ -5,7 +5,7 @@ run_range: [0, 0], construction: "hemisphere", envelope_radius: 244.0, // should be large enough to fit all objects (>flange_rmax) -front_encapsulation_material: "nakano_acrylic", +front_encapsulation_material: "acrylic_uvt_good", rear_encapsulation_material: "acrylic_black", flange_rmax: 243.0, // applies to acrylic and metal flange encap_radius: 200.0, diff --git a/ratdb/MATERIALS.ratdb b/ratdb/MATERIALS.ratdb index 76c17805..5ed79473 100644 --- a/ratdb/MATERIALS.ratdb +++ b/ratdb/MATERIALS.ratdb @@ -800,17 +800,6 @@ nmaterials: 0, elements: ["Hydrogen", "Carbon", "Oxygen"], elemprop: [0.0703, 0.558, 0.3717], } -{ -name: "MATERIAL", -index: "nakano_acrylic", -valid_begin : [0, 0], -valid_end : [0, 0], -density: 1.14, -nelements: 3, -nmaterials: 0, -elements: ["Hydrogen", "Carbon", "Oxygen"], -elemprop: [0.0703, 0.558, 0.3717], -} { name: "MATERIAL", diff --git a/ratdb/OPTICS.ratdb b/ratdb/OPTICS.ratdb index 0a6e9327..bedba88c 100644 --- a/ratdb/OPTICS.ratdb +++ b/ratdb/OPTICS.ratdb @@ -647,24 +647,6 @@ ABSLENGTH_value2: [1.0e-3, 1.0e-3, 0.49e1, 2.75e1, 10.35e1, 14.99e1, 20.41e1, 28 PROPERTY_LIST: ["RINDEX", "ABSLENGTH", ] } -{ -name : "OPTICS", -index : "nakano_acrylic", -valid_begin: [0, 0], -valid_end: [0, 0], -// Unpublished values measured internally by the BUTTON collaboration. -// Reproduced here with permission from the BUTTON collaboration. -RINDEX_option: "wavelength", -RINDEX_value1: [60.0, 200.0, 210.0, 220.0, 230.0, 240.0, 250.0, 260.0, 270.0, 280.0, 290.0, 300.0, 310.0, 320.0, 330.0, 340.0, 350.0, 360.0, 370.0, 380.0, 390.0, 400.0, 410.0, 420.0, 430.0, 440.0, 450.0, 460.0, 470.0, 480.0, 490.0, 500.0, 510.0, 520.0, 530.0, 540.0, 550.0, 560.0, 570.0, 580.0, 590.0, 600.0, 610.0, 620.0, 630.0, 640.0, 650.0, 660.0, 670.0, 680.0, 690.0, 700.0, 710.0, 720.0, 730.0, 740.0, 750.0, 760.0, 770.0, 780.0, 790.0, 800.0, ], -RINDEX_value2: [1.597, 1.597, 1.584, 1.573, 1.564, 1.556, 1.550, 1.544, 1.539, 1.534, 1.531, 1.527, 1.524, 1.521, 1.519, 1.516, 1.514, 1.512, 1.510, 1.509, 1.507, 1.506, 1.505, 1.503, 1.502, 1.501, 1.500, 1.499, 1.499, 1.498, 1.497, 1.496, 1.496, 1.495, 1.494, 1.494, 1.493, 1.493, 1.492, 1.492, 1.491, 1.491, 1.490, 1.490, 1.490, 1.489, 1.489, 1.488, 1.488, 1.488, 1.488, 1.487, 1.487, 1.487, 1.486, 1.486, 1.486, 1.486, 1.485, 1.485, 1.485, 1.485, ], -ABSLENGTH_option : "wavelength", -//New ABSLENGTH to match experimental -ABSLENGTH_value1: [60.0, 200, 300.0, 375.0, 400.0, 410.0, 420.0, 430.0, 440.0, 450.0, 460.0, 480.0, 500.0, 550.0, 800.0], -ABSLENGTH_value2: [1.0e-6, 1.0e-6, 1.0e-6, 5.56e1, 5.56e1, 8.56e1, 8.56e1, 8.56e1, 8.56e1, 8.56e1, 8.56e1, 8.56e1, 8.56e1, 8.56e1, 8.56e1], - -PROPERTY_LIST: ["RINDEX","ABSLENGTH"] -} - { name: "OPTICS", index: "acrylic_polycast", diff --git a/ratdb/Validation/WaterWorld.geo b/ratdb/Validation/WaterWorld.geo new file mode 100644 index 00000000..e8a17573 --- /dev/null +++ b/ratdb/Validation/WaterWorld.geo @@ -0,0 +1,11 @@ +{ + name: "GEO", + index: "world", + valid_begin: [0, 0], + valid_end: [0, 0], + mother: "", + type: "sphere", + r_max: 4500.0, + material: "validwater", + invisible: 0, +} From 1b67f5fea7487a1223c25cf11064175889dc0641 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Thu, 5 Jun 2025 22:54:12 +0100 Subject: [PATCH 50/52] minor changes to remove diffs --- ratdb/OPTICS.ratdb | 2 ++ ratdb/Validation/WaterWorld.geo | 11 ----------- 2 files changed, 2 insertions(+), 11 deletions(-) delete mode 100644 ratdb/Validation/WaterWorld.geo diff --git a/ratdb/OPTICS.ratdb b/ratdb/OPTICS.ratdb index bedba88c..8db299c3 100644 --- a/ratdb/OPTICS.ratdb +++ b/ratdb/OPTICS.ratdb @@ -647,6 +647,8 @@ ABSLENGTH_value2: [1.0e-3, 1.0e-3, 0.49e1, 2.75e1, 10.35e1, 14.99e1, 20.41e1, 28 PROPERTY_LIST: ["RINDEX", "ABSLENGTH", ] } + + { name: "OPTICS", index: "acrylic_polycast", diff --git a/ratdb/Validation/WaterWorld.geo b/ratdb/Validation/WaterWorld.geo deleted file mode 100644 index e8a17573..00000000 --- a/ratdb/Validation/WaterWorld.geo +++ /dev/null @@ -1,11 +0,0 @@ -{ - name: "GEO", - index: "world", - valid_begin: [0, 0], - valid_end: [0, 0], - mother: "", - type: "sphere", - r_max: 4500.0, - material: "validwater", - invisible: 0, -} From eb1e32e3a9cf558a736bf8d733838569757beea5 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Wed, 11 Jun 2025 14:19:34 +0100 Subject: [PATCH 51/52] Remove PMT statement line, 0s to nullptrs --- src/geo/src/pmt/PMTFactoryBase.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/geo/src/pmt/PMTFactoryBase.cc b/src/geo/src/pmt/PMTFactoryBase.cc index 9d683cdd..05ac9b02 100644 --- a/src/geo/src/pmt/PMTFactoryBase.cc +++ b/src/geo/src/pmt/PMTFactoryBase.cc @@ -46,11 +46,11 @@ G4VPhysicalVolume *PMTFactoryBase::ConstructPMTs( } G4ThreeVector local_offset = PMTInfoParser::ComputeLocalOffset(mother_name); - PMTEncapsulation *encap_construction = 0; - G4LogicalVolume *log_encapenv = 0; - PMTConstruction *construction = 0; - G4LogicalVolume *log_pmt = 0; - G4VPhysicalVolume *phys_mother_encap = 0; + PMTEncapsulation *encap_construction = nullptr; + G4LogicalVolume *log_encapenv = nullptr; + PMTConstruction *construction = nullptr; + G4LogicalVolume *log_pmt = nullptr; + G4VPhysicalVolume *phys_mother_encap = nullptr; G4ThreeVector pmtoffsetposition(0.0, 0.0, 0.0); int encapsulation = 0; // default to no encapsulation @@ -88,7 +88,6 @@ G4VPhysicalVolume *PMTFactoryBase::ConstructPMTs( } } - info << "Creating PMT model" << newline; construction = PMTConstruction::NewConstruction(lpmt, mother); log_pmt = construction->BuildVolume(volume_name); From d0a1fd316aa0a68caf2a2a236c819d29c21f2688 Mon Sep 17 00:00:00 2001 From: LSexton2396 Date: Wed, 11 Jun 2025 17:33:04 +0100 Subject: [PATCH 52/52] changed 0s to nullptrs for initiallising objects --- src/geo/src/pmt/HemisphereEncapsulation.cc | 33 +++++++++++----------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/geo/src/pmt/HemisphereEncapsulation.cc b/src/geo/src/pmt/HemisphereEncapsulation.cc index 8dd738e9..d6c109e4 100644 --- a/src/geo/src/pmt/HemisphereEncapsulation.cc +++ b/src/geo/src/pmt/HemisphereEncapsulation.cc @@ -22,9 +22,9 @@ namespace RAT { HemisphereEncapsulation::HemisphereEncapsulation(DBLinkPtr encaptable, DBLinkPtr pmttable, G4LogicalVolume *mother) : PMTEncapsulation("hemisphere") { - inner_encapsulation_phys = 0; - front_encapsulation_phys = 0; - rear_encapsulation_phys = 0; + inner_encapsulation_phys = nullptr; + front_encapsulation_phys = nullptr; + rear_encapsulation_phys = nullptr; fParams.envelope_radius = 0; // default to 0 try { @@ -68,8 +68,8 @@ HemisphereEncapsulation::HemisphereEncapsulation(DBLinkPtr encaptable, DBLinkPtr } catch (DBNotFoundError &e) { }; if (fParams.useMetalFlange == 1) { - front_metal_encapsulaion_flange_phys = 0; - rear_metal_encapsulation_flange_phys = 0; + front_metal_encapsulaion_flange_phys = nullptr; + rear_metal_encapsulation_flange_phys = nullptr; fParams.metal_flange_material = G4Material::GetMaterial(encaptable->GetS("metal_flange_material")); fParams.metal_flange_surface = Materials::optical_surface[encaptable->GetS("metal_flange_material")]; fParams.metal_flange_dimensions = encaptable->GetDArray("metal_flange_dimensions"); @@ -92,7 +92,7 @@ HemisphereEncapsulation::HemisphereEncapsulation(DBLinkPtr encaptable, DBLinkPtr } if (fParams.useGel == 1) { - optical_gel_encapsulation_phys = 0; + optical_gel_encapsulation_phys = nullptr; // Setup PMT parameters fParams.zEdge = pmttable->GetDArray("z_edge"); @@ -133,7 +133,7 @@ HemisphereEncapsulation::HemisphereEncapsulation(DBLinkPtr encaptable, DBLinkPtr } catch (DBNotFoundError &e) { }; if (fParams.useSilicaBag == 1) { - silica_bag_encapsulation_phys = 0; + silica_bag_encapsulation_phys = nullptr; fParams.silica_bag_material = G4Material::GetMaterial(encaptable->GetS("silica_bag_material")); fParams.silica_bag_surface = Materials::optical_surface[encaptable->GetS("silica_bag_material")]; fParams.silica_bag_dimensions = encaptable->GetDArray("silica_bag_dimensions"); @@ -146,7 +146,7 @@ HemisphereEncapsulation::HemisphereEncapsulation(DBLinkPtr encaptable, DBLinkPtr } catch (DBNotFoundError &e) { }; if (fParams.useCable == 1) { - cable_encapsulation_phys = 0; + cable_encapsulation_phys = nullptr; fParams.cable_material = G4Material::GetMaterial(encaptable->GetS("cable_material")); fParams.cable_surface = Materials::optical_surface[encaptable->GetS("cable_material")]; fParams.cable_dimensions = encaptable->GetDArray("cable_dimensions"); @@ -199,7 +199,7 @@ G4LogicalVolume *HemisphereEncapsulation::BuildVolume(const std::string &prefix) rear_encapsulation_solid = new G4UnionSolid("rear_encapsulation_solid", rear_encapsulation_solid, dome_flange_solid, 0, G4ThreeVector(0.0, 0.0, -(0.5 * fParams.encap_thickness) * CLHEP::mm)); - G4Tubs *metal_flange_solid = 0; + G4Tubs *metal_flange_solid = nullptr; if (fParams.useMetalFlange == 1) { metal_flange_solid = new G4Tubs("front_metal_flange_solid", (fParams.metal_flange_dimensions[0]) * CLHEP::mm, // rmin @@ -216,8 +216,8 @@ G4LogicalVolume *HemisphereEncapsulation::BuildVolume(const std::string &prefix) // If optical gel is used generate pmt shape to substract from gel // NOTE: THIS WILL ONLY WORK FOR TOROIDAL - G4VSolid *optical_gel_encapsulation_solid = 0; - GLG4TorusStack *body_solid = 0; + G4VSolid *optical_gel_encapsulation_solid = nullptr; + GLG4TorusStack *body_solid = nullptr; if (fParams.useGel == 1) { body_solid = (GLG4TorusStack *)BuildSolid(prefix + "_body_solid"); @@ -228,14 +228,14 @@ G4LogicalVolume *HemisphereEncapsulation::BuildVolume(const std::string &prefix) optical_gel_pmt_subtraction(prefix + "_optical_gel_encapsulation_solid", body_solid); } - G4Box *silica_bag_solid = 0; + G4Box *silica_bag_solid = nullptr; if (fParams.useSilicaBag == 1) { silica_bag_solid = new G4Box("silica_bag_solid", (fParams.silica_bag_dimensions[0]) * CLHEP::mm, (fParams.silica_bag_dimensions[1]) * CLHEP::mm, (fParams.silica_bag_dimensions[2]) * CLHEP::mm); } - G4Tubs *cable_solid = 0; + G4Tubs *cable_solid = nullptr; if (fParams.useCable == 1) { cable_solid = new G4Tubs("cable_solid", (fParams.cable_dimensions[0]) * CLHEP::mm, // rmin @@ -246,9 +246,10 @@ G4LogicalVolume *HemisphereEncapsulation::BuildVolume(const std::string &prefix) // ---------- Logical volumes ---------- - G4LogicalVolume *envelope_log, *front_encapsulation_log, *rear_encapsulation_log, *metal_flange_encapsulation_log = 0; - G4LogicalVolume *inner_encapsulation_log, *optical_gel_encapsulation_log = 0, *silica_bag_encapsulation_log = 0, - *cable_encapsulation_log = 0; + G4LogicalVolume *envelope_log, *front_encapsulation_log, *rear_encapsulation_log, + *metal_flange_encapsulation_log = nullptr; + G4LogicalVolume *inner_encapsulation_log, *optical_gel_encapsulation_log = nullptr, + *silica_bag_encapsulation_log = nullptr, *cable_encapsulation_log = nullptr; envelope_log = new G4LogicalVolume(envelope_solid, fParams.exterior_material, "envelope_log");