#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __GNUC__ #define UNUSED __attribute__((unused)) #else #define UNUSED #endif using CLHEP::mm; using CLHEP::pi; using CLHEP::twopi; using CLHEP::rad; using CLHEP::MeV; namespace RAT { void GeoN16SourceFactory::Construct( DBLinkPtr table, UNUSED const bool checkOverlaps ) { std::string prefix = table->GetS( "index" ); std::string motherName = table->GetS( "mother" ); G4LogicalVolume *mother = Detector::FindLogicalVolume( motherName ); G4Material* motherMaterial = mother->GetMaterial(); int lcn = table->GetI( "lcn" ); // Defines the colours for visualization G4Color stainlessSteelCol(0.0,1.0,0.0); G4Color acrylicSnoCol(1.0,0.0,0.0); G4Color airCol(1.0,1.0,1.0); G4Color plasticScintCol(0.0,1.0,1.0); G4Color polyethyleneCol(0.0,0.0,1.0); G4Color scintCol(1.0,1.0,0.0); G4Color aluminumCol(1.0,0.0,1.0); // Load translations from the macro file std::pair< G4ThreeVector, G4RotationMatrix* > translation; try{ table->GetDArray("position"); translation = LoadTranslation( table ); } catch (DBNotFoundError& e ) { // If there is a translation or rotation missing check if there is N16 information // loaded from ratdb LoadCalibCommon("MANIP"); if (fSourceType == "N16"){ translation.first.setX( fPosition.x() ); translation.first.setY( fPosition.y() ); translation.first.setZ( fPosition.z() ); // Now correct these by this volume's relative (if it exists) - see rat/src/geo/GeoFactory.cc try { const string relative = table->GetS( "relative" ); G4VPhysicalVolume* relativeVol = Detector::FindPhysicalVolume( relative ); if( relativeVol == NULL ) Log::Die( "GeoN16SourceFactory::Construct: No relative " + relative + " exists." ); translation.first -= relativeVol->GetFrameTranslation(); } catch( DBNotFoundError& e ) { } // This is not essential now but it may need to be (correctly) used in the future //G4ThreeVector colx = G4ThreeVector(fOrientationVector.x(), fOrientationVector.y(), 0.0); //G4ThreeVector coly = G4ThreeVector(-fOrientationVector.y(), fOrientationVector.x(), 0.); //G4ThreeVector colz = G4ThreeVector(0, 0, 0); //translation.second->set(colx, coly, colz); } else { Log::Die( "GeoN16SourceFactory::Construct: No position given and no run information exists."); } } // Offsets the n16source object so that the center of the gas chamber is where the simulation places the n16 geometery Double_t gas_chamber_offset = table->GetD( "n16_gas_chamber_offset" ) *mm; // Offsets for the weight volumes Double_t weight_cap_zpos = table->GetD( "n16_weight_cap_zpos" ) *mm; Double_t weight_zpos = table->GetD( "n16_weight_zpos" ) *mm; Double_t weight_n16_zpos = table->GetD( "n16_weight_n16_zpos" ) *mm; // Hardcoded numbers are the results explicit measurements of the source as built. // Placement of objects within the n16 source Double_t lighthouse_zpos = table->GetD( "n16_lighthouse_zpos" ) *mm; Double_t airVolume_zpos = table->GetD( "n16_airVolume_zpos" ) *mm; Double_t upperSeal_zpos = table->GetD( "n16_upperSeal_zpos" ) *mm; Double_t aluminumSleeve_zpos = table->GetD( "n16_aluminumSleeve_zpos" ) *mm; // Define the placement of the PMT within the air volume Double_t pmtCase_zpos = table->GetD( "n16_pmtCase_zpos" ) *mm; Double_t pmtCollar_zpos = table->GetD( "n16_pmtCollar_zpos" ) *mm; Double_t divider_zpos = table->GetD( "n16_divider_zpos" ) *mm; Double_t window_zpos = table->GetD( "n16_window_zpos" ) *mm; Double_t steelSleeve_zpos = table->GetD( "n16_steelSleeve_zpos" ) *mm; Double_t ptfe_zpos = table->GetD( "n16_ptfe_zpos" ) *mm; Double_t lowerSeal_zpos = table->GetD( "n16_lowerSeal_zpos" ) *mm; Double_t lockingRing_zpos = table->GetD( "n16_lockingRing_zpos" ) *mm; Double_t bumpercone_zpos = table->GetD( "n16_bumpercone_zpos" ) *mm; // extract the tube dimensions from the database. // arrays are [inner_radius, outer_radius, height] std::vector n16_weight_cap_par = table->GetDArray("n16_weight_cap_par"); std::vector n16_weight_par = table->GetDArray("n16_weight_par"); std::vector n16_weightN16_par = table->GetDArray("n16_weightN16_par"); // All the volumes required for building the source ordered from top to bottom // Defining the weight canister that is attached to the top of the n16 source tube G4VSolid* weightCap = new G4Tubs( prefix + "_weight_cap", n16_weight_cap_par[0]*mm, n16_weight_cap_par[1]*mm, n16_weight_cap_par[2]*mm, 0.0, twopi ); G4VSolid* weight = new G4Tubs( prefix + "_weight", n16_weight_par[0]*mm, n16_weight_par[1]*mm, n16_weight_par[2]*mm, 0.0, twopi); G4VSolid* weightN16 = new G4Tubs( prefix + "_weight_n16", n16_weightN16_par[0]*mm, n16_weightN16_par[1]*mm, n16_weightN16_par[2]*mm, 0.0, twopi ); // Defining the source tube for the bulk of the source std::vector n16_source_par = table->GetDArray("n16_source_par"); G4VSolid* n16Source = new G4Tubs( prefix + "_source", n16_source_par[0]*mm, n16_source_par[1]*mm, n16_source_par[2]*mm, 0.0, twopi ); // Lighthouse volume where liquid is free to enter // Note: dimensions are taken from measurments of real component. Double_t z_lighthouse[6] = {0.0*mm, 5.49*mm, 5.49*mm, 77.23*mm, 77.23*mm, 81.07*mm}; Double_t r_inner_lighthouse[6] = {0.0*mm, 0.0*mm, 0.0*mm, 0.0*mm, 0.0*mm, 0.0*mm}; Double_t r_outer_lighthouse[6] = {41.78*mm, 41.78*mm, 53.98*mm, 53.98*mm, 41.78*mm, 41.78*mm}; G4VSolid* lighthouse = new G4Polycone( prefix + "_lighthouse0", 0.0 , twopi , 6, z_lighthouse, r_inner_lighthouse, r_outer_lighthouse ); G4VSolid* cutout = new G4Tubs( prefix + "_cutout", 53.98*mm, 57.22*mm, 28.47*mm, 0.0, 0.44*rad ); G4RotationMatrix* zRot = new G4RotationMatrix; zRot->rotateZ(pi/4); Double_t z_lhoffset = table->GetD( "z_lhoffset" ) *mm; G4UnionSolid* lighthouseAdd0 = new G4UnionSolid( prefix + "_lighthouse1", lighthouse, cutout, zRot, G4ThreeVector( 0.0*mm, 0.0*mm, z_lhoffset ) ); zRot->rotateZ(pi/2); G4UnionSolid* lighthouseAdd1 = new G4UnionSolid( prefix + "_lighthouse2", lighthouseAdd0, cutout, zRot, G4ThreeVector( 0.0*mm, 0.0*mm, z_lhoffset ) ); zRot->rotateZ(3*pi/4); G4UnionSolid* lighthouseAdd2 = new G4UnionSolid( prefix + "_lighthouse3", lighthouseAdd1, cutout, zRot, G4ThreeVector( 0.0*mm, 0.0*mm, z_lhoffset ) ); zRot->rotateZ(pi); G4UnionSolid* lighthouseAdd3 = new G4UnionSolid( prefix + "_lighthouse4", lighthouseAdd2, cutout, zRot, G4ThreeVector( 0.0*mm, 0.0*mm, z_lhoffset ) ); zRot->rotateZ(5*pi/4); G4UnionSolid* lighthouseAdd4 = new G4UnionSolid( prefix + "_lighthouse5", lighthouseAdd3, cutout, zRot, G4ThreeVector( 0.0*mm, 0.0*mm, z_lhoffset ) ); zRot->rotateZ(3*pi/2); G4UnionSolid* lighthouseAdd5 = new G4UnionSolid( prefix + "_lighthouse6", lighthouseAdd4, cutout, zRot, G4ThreeVector( 0.0*mm, 0.0*mm, z_lhoffset ) ); zRot->rotateZ(7*pi/4); G4UnionSolid* lighthouseAdd6 = new G4UnionSolid( prefix + "_lighthouse7", lighthouseAdd5, cutout, zRot, G4ThreeVector( 0.0*mm, 0.0*mm, z_lhoffset ) ); zRot->rotateZ(pi); G4UnionSolid* lighthouseAdd7 = new G4UnionSolid( prefix + "_lighthouse8", lighthouseAdd6, cutout, zRot, G4ThreeVector( 0.0*mm, 0.0*mm, z_lhoffset ) ); // Air volume inside the source std::vector n16_airVolume_par = table->GetDArray("n16_airVolume_par"); G4VSolid* airVolume = new G4Tubs( prefix + "_air", n16_airVolume_par[0]*mm, n16_airVolume_par[1]*mm, n16_airVolume_par[2]*mm, 0.0, twopi ); // Locking Ring, prevents the sealing ring from moving std::vector n16_lockingRing_par = table->GetDArray("n16_lockingRing_par"); G4VSolid* lockingRing = new G4Tubs( prefix + "_locking_ring", n16_lockingRing_par[0]*mm, n16_lockingRing_par[1]*mm, n16_lockingRing_par[2]*mm, 0.0, twopi ); // Upper Sealing Ring std::vector n16_upperSeal_par = table->GetDArray("n16_upperSeal_par"); G4VSolid* upperSeal = new G4Tubs( prefix + "_upper_seal", n16_upperSeal_par[0]*mm, n16_upperSeal_par[1]*mm, n16_upperSeal_par[2]*mm, 0.0, twopi ); // Aluminum sleeve that goes inside the upper volume of the source std::vector n16_aluminumSleeve_par = table->GetDArray("n16_aluminumSleeve_par"); G4VSolid* aluminumSleeve = new G4Tubs( prefix + "_aluminum_sleeve", n16_aluminumSleeve_par[0]*mm, n16_aluminumSleeve_par[1]*mm, n16_aluminumSleeve_par[2]*mm, 0.0, twopi ); // Building the PMT with the constructor G4Material* windowMaterial = G4Material::GetMaterial( "glass" ); Initialise( prefix, windowMaterial ); G4VisAttributes *attrib = new G4VisAttributes; attrib->SetForceSolid( true ); PMTConstructorParams params( "N16PMT", attrib ); ConstructPMT( 0, params ); AssembleFullPMT( 0, attrib ); SetupFullOpticalModel( 0 ); string pmtName = prefix + "_pmtenv_" + ::to_string(lcn); G4ThreeVector pmtPos( 0, 0, 40.94 ); G4ThreeVector pmtDir( 0.0, 0.0, 1.0 ); CorrectPMTPosAndDir(DU::PMTInfo::CALIB, pmtPos, pmtDir); // Black plastic case that holds the PMT // Note: dimensions are taken from measurments of real component. Double_t z_pmtCase[4] = {0.0*mm, 37.21*mm, 37.21*mm, 43.21*mm}; Double_t r_inner_pmtCase[4] = {25.91*mm, 25.91*mm, 25.91*mm, 25.91*mm}; Double_t r_outer_pmtCase[4] = {27.78*mm, 27.78*mm, 31.35*mm, 31.34*mm}; G4VSolid* pmtCase = new G4Polycone( prefix + "_pmt_case", 0.0, twopi, 4, z_pmtCase, r_inner_pmtCase, r_outer_pmtCase ); // Aluminum collar that the PMT case rests on and screws into the divider // Note: dimensions are taken from measurments of real component. Double_t z_collar[4] = {0.0*mm, 7.99*mm, 7.99*mm, 33.41*mm}; Double_t r_inner_collar[4] = {28.96*mm, 28.96*mm, 28.96*mm, 28.96*mm}; Double_t r_outer_collar[4] = {47.63*mm, 47.63*mm, 32.77*mm, 32.77*mm}; G4VSolid* pmtCollar = new G4Polycone( prefix + "_pmt_collar", 0.0, twopi, 4, z_collar, r_inner_collar, r_outer_collar ); std::vector n16_pmtCollarPenetration_par = table->GetDArray("n16_pmtCollarPenetration_par"); G4VSolid* pmtCollarPenetration = new G4Tubs(prefix + "_pmt_collar_penetration", n16_pmtCollarPenetration_par[0]*mm, n16_pmtCollarPenetration_par[1]*mm, n16_pmtCollarPenetration_par[2]*mm, 0.0, twopi ); G4SubtractionSolid* pmtCollarSub0 = new G4SubtractionSolid( prefix + "_pmt_collar", pmtCollar, pmtCollarPenetration, 0, G4ThreeVector( -37.84*mm, 0.0*mm, 0.0*mm ) ); G4SubtractionSolid* pmtCollarSub1 = new G4SubtractionSolid( prefix + "_pmt_collar", pmtCollarSub0, pmtCollarPenetration, 0, G4ThreeVector( 37.84*mm, 0.0*mm, 0.0*mm ) ); // Divider that seperates the lower gas volume from the electronics Double_t z_divider[4] = { 0.0*mm, 9.64*mm, 9.64*mm, 19*mm }; Double_t r_inner_divider[4] = { 30.01*mm, 30.01*mm, 32.67*mm, 32.67*mm }; Double_t r_outer_divider[4] = { 52.8*mm, 52.8*mm, 52.8*mm, 52.8*mm }; G4VSolid* divider = new G4Polycone( prefix + "_divider", 0.0, twopi, 4, z_divider, r_inner_divider, r_outer_divider ); std::vector n16_gasPenetration_par = table->GetDArray("n16_gasPenetration_par"); G4VSolid* gasPenetration = new G4Tubs( prefix + "_gas_pen_sub", n16_gasPenetration_par[0]*mm, n16_gasPenetration_par[1]*mm, n16_gasPenetration_par[2]*mm, 0.0, twopi ); std::vector n16_gasTube_par = table->GetDArray("n16_gasTube_par"); G4VSolid* gasTube = new G4Tubs( prefix + "_gas_tube", n16_gasTube_par[0]*mm, n16_gasTube_par[1]*mm, n16_gasTube_par[2]*mm, 0.0, twopi ); std::vector n16_gasPlug_par = table->GetDArray("n16_gasPlug_par"); G4VSolid* gasPlug = new G4Tubs( prefix + "_gas_plug", n16_gasPlug_par[0]*mm, n16_gasPlug_par[1]*mm, n16_gasPlug_par[2]*mm, 0.0, twopi ); G4SubtractionSolid* dividerSub0 = new G4SubtractionSolid( prefix + "_divider_sub0", divider, gasPenetration, 0, G4ThreeVector( -37.84*mm, 0.0*mm, 0.0*mm ) ); G4SubtractionSolid* dividerSub1 = new G4SubtractionSolid( prefix + "_divider_sub1", dividerSub0, gasPenetration, 0, G4ThreeVector( 37.84*mm, 0.0*mm, 0.0*mm ) ); G4UnionSolid* dividerAdd0 = new G4UnionSolid( prefix + "_divider_add0", dividerSub1, gasTube, 0, G4ThreeVector( -37.84*mm, 0.0*mm, 49.5*mm ) ); G4UnionSolid* dividerAdd1 = new G4UnionSolid( prefix + "_divider_add1", dividerAdd0, gasTube, 0, G4ThreeVector( 37.84*mm, 0.0*mm, 49.5*mm ) ); G4UnionSolid* dividerAdd2 = new G4UnionSolid( prefix + "_divider_add2", dividerAdd1, gasPlug, 0, G4ThreeVector( 37.84*mm, 0.0*mm, 91.5*mm ) ); // Arcylic window that sees the lights from internal betas // Note: dimensions are taken from measurments of real component. Double_t z_window[4] = { 0.0*mm, 8.07*mm, 8.07*mm, 17.43*mm }; Double_t r_inner_window[4] = { 0.0*mm, 0.0*mm, 26.09*mm, 26.09*mm }; Double_t r_outer_window[4] = { 30.01*mm, 30.01*mm, 32.67*mm, 32.67*mm }; G4VSolid* window = new G4Polycone( prefix + "_window", 0.0, twopi, 4, z_window, r_inner_window, r_outer_window ); // Stainless steel sleeve that adds extra shielding around the scintillator volume std::vector n16_steelSleeve_par = table->GetDArray("n16_steelSleeve_par"); G4VSolid* steelSleeve = new G4Tubs( prefix + "_steel_sleeve", n16_steelSleeve_par[0]*mm, n16_steelSleeve_par[1]*mm, n16_steelSleeve_par[2]*mm, 0.0, twopi ); // PTFE teflon tape which is wrapped around the scintillator tube // Note: dimensions are taken from measurments of real component. Double_t z_reflect[6] = {0.0*mm, 0.06*mm, 0.06*mm, 159.94*mm, 159.94*mm, 160.0*mm}; Double_t r_inner_reflect[6] = {0.0*mm, 0.0*mm, 49.39*mm, 49.39*mm, 28.11*mm, 28.11*mm}; Double_t r_outer_reflect[6] = {49.45*mm, 49.45*mm, 49.45*mm, 49.45*mm, 49.45*mm, 49.45*mm}; G4VSolid* ptfe = new G4Polycone( prefix + "_ptfe", 0.0, twopi, 6, z_reflect, r_inner_reflect, r_outer_reflect ); G4SubtractionSolid* ptfeSub0 = new G4SubtractionSolid( prefix + "_ptfe_sub0", ptfe, gasPenetration, 0, G4ThreeVector( -37.84*mm, 0.0*mm, 160.0*mm ) ); G4SubtractionSolid* ptfeSub1 = new G4SubtractionSolid( prefix + "_ptfe_sub1", ptfeSub0, gasPenetration, 0, G4ThreeVector( 37.84*mm, 0.0*mm, 160.0*mm ) ); // Scintillator tube std::vector n16_scint_par = table->GetDArray("n16_scint_par"); G4VSolid* scint = new G4Tubs( prefix + "_scint", n16_scint_par[0]*mm, n16_scint_par[1]*mm, n16_scint_par[2]*mm, 0.0, twopi ); std::vector n16_gas_par = table->GetDArray("n16_gas_par"); G4VSolid* gas = new G4Tubs( prefix + "_gas", n16_gas_par[0]*mm, n16_gas_par[1]*mm, n16_gas_par[2]*mm, 0.0, twopi ); G4SubtractionSolid* scintSub0 = new G4SubtractionSolid( prefix + "_scint_sub0", scint, gasPenetration, 0, G4ThreeVector( -37.84*mm, 0.0*mm, 80.0*mm ) ); G4SubtractionSolid* scintSub1 = new G4SubtractionSolid( prefix + "_scint_sub1", scintSub0, gasPenetration, 0, G4ThreeVector( 37.84*mm, 0.0*mm, 80.0*mm ) ); G4SubtractionSolid* scintSub2 = new G4SubtractionSolid( prefix + "_scint_sub2", scintSub1, gas, 0, G4ThreeVector( 0.0*mm, 0.0*mm, 0.0*mm ) ); // Lower Sealing Ring std::vector n16_lowerSeal_par = table->GetDArray("n16_lowerSeal_par"); G4VSolid* lowerSeal = new G4Tubs( prefix + "_lower_seal", n16_lowerSeal_par[0]*mm, n16_lowerSeal_par[1]*mm, n16_lowerSeal_par[2]*mm, 0.0, twopi ); // Polyethylene cone at the bottom of the source Double_t z_bumper[3] = {0.0*mm, 54.58*mm, 57.79*mm}; Double_t r_inner_bumper[3] = {0.0*mm, 0.0*mm, 0.0*mm}; Double_t r_outer_bumper[3] = {3.41*mm, 57.18*mm, 57.18*mm}; G4VSolid* bumper = new G4Polycone( prefix + "_bumper", 0.0 , twopi , 3, z_bumper, r_inner_bumper, r_outer_bumper ); // Setting all the logical volumes for all the pieces G4LogicalVolume* weightCapLog = new G4LogicalVolume( weightCap, G4Material::GetMaterial( "stainless_steel" ), prefix + "_weight_cap_logic" ); G4LogicalVolume* weightLog = new G4LogicalVolume( weight, G4Material::GetMaterial( "stainless_steel" ), prefix + "_weight_logic" ); G4LogicalVolume* weightN16Log = new G4LogicalVolume( weightN16, G4Material::GetMaterial( "stainless_steel" ), prefix + "_weight_n16_logic"); G4LogicalVolume* n16SourceLog = new G4LogicalVolume( n16Source, G4Material::GetMaterial( "stainless_steel" ), prefix + "_logic" ); G4LogicalVolume* lighthouseLog = new G4LogicalVolume( lighthouseAdd7, motherMaterial, prefix + "_lighthouse_logic" ); G4LogicalVolume* airVolumeLog = new G4LogicalVolume( airVolume, G4Material::GetMaterial( "air" ), prefix + "_air_logic" ); G4LogicalVolume* lockingRingLog = new G4LogicalVolume( lockingRing, G4Material::GetMaterial( "stainless_steel" ), prefix + "_locking_ring_logic" ); G4LogicalVolume* upperSealLog = new G4LogicalVolume( upperSeal, G4Material::GetMaterial( "stainless_steel" ), prefix + "_upper_seal_logic" ); G4LogicalVolume* aluminumSleeveLog = new G4LogicalVolume( aluminumSleeve, G4Material::GetMaterial( "aluminum" ), prefix + "_aluminum_sleeve_log" ); G4LogicalVolume* pmtCaseLog = new G4LogicalVolume( pmtCase, G4Material::GetMaterial( "ABSplastic" ), prefix + "_pmt_case_logic" ); G4LogicalVolume* pmtCollarLog = new G4LogicalVolume( pmtCollarSub1, G4Material::GetMaterial( "aluminum" ), prefix + "_pmt_collar_logic" ); G4LogicalVolume* dividerLog = new G4LogicalVolume( dividerAdd2, G4Material::GetMaterial( "stainless_steel"), prefix + "_divider_logic" ); G4LogicalVolume* windowLog = new G4LogicalVolume( window, G4Material::GetMaterial( "acrylic_sno" ), prefix + "_window_logic" ); G4LogicalVolume* steelSleeveLog = new G4LogicalVolume( steelSleeve, G4Material::GetMaterial( "stainless_steel" ), prefix + "_logic" ); G4LogicalVolume* ptfeLog = new G4LogicalVolume( ptfeSub1, G4Material::GetMaterial( "ptfe" ), prefix + "_scint_reflect_logic" ); G4LogicalVolume* scintLog = new G4LogicalVolume( scintSub2, G4Material::GetMaterial( "G4_PLASTIC_SC_VINYLTOLUENE" ), prefix + "_scint_logic" ); G4LogicalVolume* gasLog = new G4LogicalVolume( gas, G4Material::GetMaterial( "air" ), prefix + "_gas_logic" ); G4LogicalVolume* lowerSealLog = new G4LogicalVolume( lowerSeal, G4Material::GetMaterial( "stainless_steel" ), prefix + "_lower_seal_logic" ); G4LogicalVolume* bumperLog = new G4LogicalVolume( bumper, G4Material::GetMaterial( "polyethylene" ), prefix + "_bumper_logic" ); // Setting the visibility attributes for all the volumes weightCapLog->SetVisAttributes( stainlessSteelCol ); weightLog->SetVisAttributes( stainlessSteelCol ); weightN16Log->SetVisAttributes( stainlessSteelCol ); n16SourceLog->SetVisAttributes( stainlessSteelCol ); lighthouseLog->SetVisAttributes( scintCol ); airVolumeLog->SetVisAttributes( airCol ); lockingRingLog->SetVisAttributes( stainlessSteelCol ); upperSealLog->SetVisAttributes( stainlessSteelCol ); aluminumSleeveLog->SetVisAttributes( aluminumCol ); pmtCaseLog->SetVisAttributes( polyethyleneCol ); pmtCollarLog->SetVisAttributes( aluminumCol ); dividerLog->SetVisAttributes( stainlessSteelCol ); windowLog->SetVisAttributes( acrylicSnoCol ); steelSleeveLog->SetVisAttributes( stainlessSteelCol ); ptfeLog->SetVisAttributes( acrylicSnoCol ); gasLog->SetVisAttributes( airCol ); lowerSealLog->SetVisAttributes( stainlessSteelCol ); bumperLog->SetVisAttributes( polyethyleneCol ); // Now position the entire source in the detector // Position by the centre of the gas volume, shifted for mother vol // The z numbers come from the relative positioning of the gas volume (i.e. the volume filled by the n16 generator) // relative to the n16Source volume (i.e. the volume positioned in the macro). translation.first.setZ( translation.first.z() + gas_chamber_offset ); // Places the logical volumes of the weight canister and it's components new G4PVPlacement( 0, G4ThreeVector( translation.first.x(), translation.first.y(), (translation.first.z()+weight_cap_zpos) ), prefix + "_weight_cap_phys", weightCapLog, Detector::FindPhysicalVolume( motherName ), false, 0 ); new G4PVPlacement( 0, G4ThreeVector( translation.first.x(), translation.first.y(), (translation.first.z()+weight_zpos) ), prefix + "_weight_phys",weightLog, Detector::FindPhysicalVolume( motherName ), false, 0 ); new G4PVPlacement( 0, G4ThreeVector( translation.first.x(), translation.first.y(), (translation.first.z()+weight_n16_zpos) ), prefix + "_weight_n16", weightN16Log, Detector::FindPhysicalVolume( motherName ), false, 0 ); // Places the n16source logical volume new G4PVPlacement( 0, G4ThreeVector( translation.first.x(), translation.first.y(), (translation.first.z()) ), prefix + "_source_phys",n16SourceLog, Detector::FindPhysicalVolume( motherName) , false, 0 ); // Places all the logical volumes within the n16source new G4PVPlacement( 0, G4ThreeVector( 0.0*mm, 0.0*mm, lighthouse_zpos ), lighthouseLog, prefix + "_lighthouse_phys", n16SourceLog, false, 0 ); new G4PVPlacement( 0, G4ThreeVector( 0.0*mm, 0.0*mm, airVolume_zpos ), airVolumeLog, prefix + "_air_phys", n16SourceLog, false, 0 ); new G4PVPlacement( 0, G4ThreeVector( 0.0*mm, 0.0*mm, upperSeal_zpos ), upperSealLog, prefix + "_upper_seal_phys", airVolumeLog, false, 0 ); new G4PVPlacement( 0, G4ThreeVector( 0.0*mm, 0.0*mm, aluminumSleeve_zpos ), aluminumSleeveLog, prefix + "_aluminum_sleeve_phys", airVolumeLog, false, 0 ); // PMT requires a rotation to be put in facing the correct direction G4RotationMatrix* xRot = new G4RotationMatrix; xRot->rotateX(pi); new G4PVPlacement( xRot, pmtPos, fEnvelope[0]->GetLogicalVolume(), pmtName, pmtCaseLog, false, lcn ); new G4PVPlacement( 0, G4ThreeVector( 0.0*mm, 0.0*mm, pmtCase_zpos ), pmtCaseLog, prefix + "_pmt_case_phys", airVolumeLog, false, 0 ); new G4PVPlacement( 0, G4ThreeVector( 0.0*mm, 0.0*mm, pmtCollar_zpos ), pmtCollarLog, prefix + "_pmt_collar_phys", airVolumeLog, false, 0 ); new G4PVPlacement( 0, G4ThreeVector( 0.0*mm, 0.0*mm, divider_zpos ), dividerLog, prefix + "_divider_phys", airVolumeLog, false, 0 ); new G4PVPlacement( 0, G4ThreeVector( 0.0*mm, 0.0*mm, window_zpos ), windowLog, prefix + "_window_phys", airVolumeLog, false, 0 ); new G4PVPlacement( 0, G4ThreeVector( 0.0*mm, 0.0*mm, steelSleeve_zpos ), steelSleeveLog, prefix + "_scint_sleeve_phys", airVolumeLog, false, 0 ); new G4PVPlacement( 0, G4ThreeVector( 0.0*mm, 0.0*mm, ptfe_zpos ), ptfeLog, prefix + "_scint_reflect_phys", airVolumeLog, false, 0 ); new G4PVPlacement( 0, G4ThreeVector( 0.0*mm, 0.0*mm, steelSleeve_zpos ), scintLog, prefix + "_scint_phys", airVolumeLog, false, 0 ); new G4PVPlacement( 0, G4ThreeVector( 0.0*mm, 0.0*mm, steelSleeve_zpos ), gasLog, prefix + "_gas_phys", airVolumeLog, false, 0 ); new G4PVPlacement( 0, G4ThreeVector( 0.0*mm, 0.0*mm, lowerSeal_zpos ), lowerSealLog, prefix + "_upper_seal_phys", airVolumeLog, false, 0 ); new G4PVPlacement( 0, G4ThreeVector( 0.0*mm, 0.0*mm, lockingRing_zpos ), lockingRingLog, prefix + "_locking_ring_phys", airVolumeLog, false, 0 ); // Places the bumper cone logical volume new G4PVPlacement( 0, G4ThreeVector( translation.first.x(), translation.first.y(), (translation.first.z()+bumpercone_zpos) ), prefix + "_bumper_phys", bumperLog, Detector::FindPhysicalVolume( motherName), false, 0 ); // Make the scintillator detectable by the PMT G4SDManager* sDManager = G4SDManager::GetSDMpointer(); CalibPMTSD* pmtSD = new CalibPMTSD(pmtName, lcn, 0.1*MeV, 1.0); sDManager->AddNewDetector(pmtSD); scintLog->SetSensitiveDetector(pmtSD); scintLog->SetVisAttributes( scintCol ); } // Reproduced from SOCDataProc void GeoN16SourceFactory::LoadCalibCommon(std::string fCalInfo) { if (fCalInfo != "MANIP" && fCalInfo != "CAMERA") Log::Die("GeoN16SourceFactory::LoadCalibCommon CalInfo "+ fCalInfo + " not recognized. Choose MANIP or CAMERA."); DBLinkPtr lCAL_SOURCE = DB::Get()->GetLink("CALIB_COMMON_RUN_LEVEL",fCalInfo); fSourceType = lCAL_SOURCE->GetS("source_type"); bool aPositionValid = lCAL_SOURCE->GetZ("position_valid"); bool aPositionBitmask = lCAL_SOURCE->GetI("position_bitmask"); if (!aPositionValid) Log::Die("GeoN16SourceFactory::LoadCalibCommon Position error: " + ::to_string(aPositionBitmask)); std::vector aPosition = lCAL_SOURCE->GetFArrayFromD("position"); fPosition.SetXYZ(aPosition[0], aPosition[1], aPosition[2]); double aOrientation = lCAL_SOURCE->GetD("orientation"); // If info source is manip, orientation should be an integer (converted to float) // If info source is camera, orientation can be any value (but should match manip...) float or_x=0.0, or_y=0.0; if (fCalInfo == "MANIP"){ if (fabs(aOrientation) <0.01) { //East or_x = 1.0; or_y = 0.0; } else if (fabs(aOrientation - 1.0) <0.01) { //North or_x = 0.0; or_y = 1.0; } else if (fabs(aOrientation - 2.0) <0.01) { //West or_x = -1.0; or_y = 0.0; } else if (fabs(aOrientation - 3.0) <0.01) { //South or_x = 0.0; or_y = -1.0; } else { warn << "GeoN16SourceFactory::LoadCalibCommon MANIP option chosen but orientation read from ratdb is not close to an integer: "<< aOrientation << ". Using default orientation 0(East)."; aOrientation = 0.0; or_x = 1.0; or_y = 0.0; } } else { or_x = cos(aOrientation*ROOT::Math::Pi()/2.0); or_y = sin(aOrientation*ROOT::Math::Pi()/2.0); } fOrientationVector = TVector3(or_x, -or_y,0.0); } } // namespace RAT