From f7a3ddccfb9d29f713842f3a3e3781b837c8edb6 Mon Sep 17 00:00:00 2001 From: Christopher Dilks Date: Wed, 3 May 2023 09:22:00 -0400 Subject: [PATCH 1/8] fix(dRICH): adjust sensor region boundaries (#418) ### Briefly, what does this PR introduce? Adjust `sphericalpatch` cuts, which define the limits of the sensor sphere. Previous limits: ``` rmin = "DRICH_rmax1 + 3.0*cm" = 107.656 cm rmax = "DRICH_rmax2 - 3.0*cm" = 182.000 cm ``` New limits from Luca: ``` rmin = 110 cm, but actually needs to be 111 cm to remove extra "dangling" sensors at low theta rmax = 179 cm ``` ### What kind of change does this PR introduce? - [x] Bug fix (engineering constraints) - [ ] New feature (issue #__) - [ ] Documentation update - [ ] Other: __ ### Please check if this PR fulfills the following: - [x] Tests for the changes have been added - [ ] Documentation has been added / updated - [x] Changes have been communicated to collaborators @chchatte92 ### Does this PR introduce breaking changes? What changes might users need to make to their code? no ### Does this PR change default behavior? no, but slight change in polar acceptance boundary --- compact/pid/drich.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compact/pid/drich.xml b/compact/pid/drich.xml index 67e30071c8..1d23e5a4d4 100644 --- a/compact/pid/drich.xml +++ b/compact/pid/drich.xml @@ -216,8 +216,8 @@ /> From 0bbcac92983f076a085a9dc2e3ec596613b63942 Mon Sep 17 00:00:00 2001 From: niwgit Date: Thu, 4 May 2023 13:19:54 -0400 Subject: [PATCH 2/8] Use 3-layer spherical lens for hpDIRC (#394) ### Briefly, what does this PR introduce? A few changes related to the geometry of the lens to match with the standalone simulation. - disable the shift of optical axis compared to bar center - use 3-layer spherical lenses instead of cylindrical lens - use Sapphire material for the lens 2nd layer and add material properties for Sapphire ### What kind of change does this PR introduce? - [x] Bug fix (issue #__) - [ ] New feature (issue #__) - [ ] Documentation update - [ ] Other: __ ### Please check if this PR fulfills the following: - [ ] Tests for the changes have been added - [ ] Documentation has been added / updated - [ ] Changes have been communicated to collaborators ### Does this PR introduce breaking changes? What changes might users need to make to their code? ### Does this PR change default behavior? --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christopher Dilks Co-authored-by: Wouter Deconinck --- compact/optical_materials.xml | 259 +++++++++++++++++++++++++++++++++- compact/pid/dirc.xml | 28 ++-- src/DIRC_geo.cpp | 116 ++++++++------- 3 files changed, 340 insertions(+), 63 deletions(-) diff --git a/compact/optical_materials.xml b/compact/optical_materials.xml index b791d4f92d..aaa3897a70 100644 --- a/compact/optical_materials.xml +++ b/compact/optical_materials.xml @@ -7,6 +7,82 @@ 1.0*eV 1.0 5.1*eV 1.0 "/> + + + + + + Absorption length is caculated using transmittance values for 2 mm thickness (crystan standard UV grade) from + https://www.crystran.co.uk/optical-materials/sapphire-al2o3 + + F = ((n - 1) * (n - 1)) / ((n + 1) * (n + 1)) + + Absorption length = (-1 / ln(transmittance + 2*F)) * 2 mm + where: + F - Fresnel reflection coefficient + n - Refractive index of Sapphire + + + + - - + + @@ -809,6 +1054,13 @@ Nlak33aMaterial->AddElement(O, natoms = 2); --> + + + + + + + @@ -848,6 +1100,9 @@ --> + + + diff --git a/compact/pid/dirc.xml b/compact/pid/dirc.xml index d82159dcf6..42437a1f9c 100644 --- a/compact/pid/dirc.xml +++ b/compact/pid/dirc.xml @@ -32,9 +32,13 @@ - + + + + + @@ -45,8 +49,8 @@ - - + + @@ -56,8 +60,6 @@ - - @@ -94,7 +96,7 @@ - + @@ -127,11 +129,11 @@ repeat_y="DIRCBar_count_y" repeat_z="DIRCBar_count_z" gap="DIRCBar_gap" - material="Quartz" + material="QuartzOptical" vis="DIRCBar" /> - + @@ -163,7 +165,7 @@ height="DIRCMCP_height" width="DIRCMCP_width" thickness="DIRCMCP_thickness" - material="Quartz" + material="QuartzOptical" vis="DIRCMCP" /> diff --git a/src/DIRC_geo.cpp b/src/DIRC_geo.cpp index f42c0054cc..29db0c2adf 100644 --- a/src/DIRC_geo.cpp +++ b/src/DIRC_geo.cpp @@ -64,21 +64,11 @@ static Ref_t createDetector(Detector& desc, xml_h e, SensitiveDetector sens) Volume glue_vol("glue_vol", glue_box, desc.material(xml_glue.materialStr())); glue_vol.setVisAttributes(desc.visAttributes(xml_glue.visStr())); - // Place bars + glue into module assembly - // FIXME place bars + glue into separate box volume auto bar_repeat_y = xml_bar.attr(_Unicode(repeat_y)); auto bar_repeat_z = xml_bar.attr(_Unicode(repeat_z)); auto bar_gap = xml_bar.gap(); auto bar_assm_width = (bar_width + bar_gap) * bar_repeat_y - bar_gap; auto bar_assm_length = (bar_length + glue_thickness) * bar_repeat_z; - for (int y_index = 0; y_index < bar_repeat_y; y_index++) { - double y = 0.5 * bar_assm_width - 0.5 * bar_width - (bar_width + bar_gap) * y_index; - for (int z_index = 0; z_index < bar_repeat_z; z_index++) { - double z = 0.5 * bar_assm_length - 0.5 * bar_length - (bar_length + glue_thickness) * z_index; - dirc_module.placeVolume(glue_vol, Position(0, y, z - 0.5 * (bar_length + glue_thickness))); - dirc_module.placeVolume(bar_vol, Position(0, y, z)).addPhysVolID("section", z_index).addPhysVolID("bar", y_index); - } - } // Mirror construction xml_comp_t xml_mirror = xml_module.child(_Unicode(mirror)); @@ -91,12 +81,26 @@ static Ref_t createDetector(Detector& desc, xml_h e, SensitiveDetector sens) // Mirror optical surface auto surfMgr = desc.surfaceManager(); - auto surf = surfMgr.opticalSurface("MirrorOpticalSurface"); + auto surf = surfMgr.opticalSurface("DIRC_MirrorOpticalSurface"); SkinSurface skin(desc, det, Form("dirc_mirror_optical_surface"), surf, mirror_vol); skin.isValid(); + // Envelope for bars + mirror + Box Envelope_box("Envelope_box", (mirror_height + 1*mm)/2, 5*(bar_width + 0.15*mm), 2*(bar_length + glue_thickness) + 0.5*mirror_thickness); + Volume Envelope_box_vol("Envelope_box_vol", Envelope_box, desc.material("AirOptical")); + dirc_module.placeVolume(Envelope_box_vol, Position(0, 0, 0.5*mirror_thickness)); + + for (int y_index = 0; y_index < bar_repeat_y; y_index++) { + double y = 0.5 * bar_assm_width - 0.5 * bar_width - (bar_width + bar_gap) * y_index; + for (int z_index = 0; z_index < bar_repeat_z; z_index++) { + double z = 0.5 * bar_assm_length - 0.5 * mirror_thickness - 0.5 * bar_length - (bar_length + glue_thickness) * z_index; + Envelope_box_vol.placeVolume(glue_vol, Position(0, y, z - 0.5 * (bar_length + glue_thickness))); + Envelope_box_vol.placeVolume(bar_vol, Position(0, y, z)).addPhysVolID("section", z_index).addPhysVolID("bar", y_index); + } + } + // Place mirror - dirc_module.placeVolume(mirror_vol, Position(0, 0, 0.5 * (bar_assm_length + mirror_thickness))); + Envelope_box_vol.placeVolume(mirror_vol, Position(0, 0, 0.5 * bar_assm_length)); // Prism variables xml_comp_t xml_prism = xml_module.child(_Unicode(prism)); @@ -108,46 +112,39 @@ static Ref_t createDetector(Detector& desc, xml_h e, SensitiveDetector sens) // Lens variables xml_comp_t xml_lens = xml_module.child(_Unicode(lens)); - double lens_height = getAttrOrDefault(xml_lens, _Unicode(height), 50 * mm); double lens_shift = getAttrOrDefault(xml_lens, _Unicode(shift), 0 * mm); - // double lens_width = getAttrOrDefault(xml_lens, _Unicode(width), 25 * mm); + double lens_width = getAttrOrDefault(xml_lens, _Unicode(width), 35 * mm); double lens_thickness = getAttrOrDefault(xml_lens, _Unicode(thickness), 12 * mm); double lens_r1 = getAttrOrDefault(xml_lens, _Unicode(r1), 62 * mm); double lens_r2 = getAttrOrDefault(xml_lens, _Unicode(r2), 36 * mm); // Lens construction - // FIXME avoid negative impact of booleans by putting lens inside box + // 3-layer spherical lens --- - // lens_min_thickness is distance from face to r1, and from r1 to r2 at lens top edge - double lens_min_thickness = 0.5 * mm; - double layer01 = 1.0 * lens_min_thickness; - double layer12 = 2.0 * lens_min_thickness; + double lens_radius = sqrt(lens_width * lens_width / 4. + bar_height * bar_height / 4.); - // ztrans1 and ztrans2 are the z shifts of the lens center for r1 and r2 - double ztrans1 = lens_thickness / 2. + sqrt(lens_r1 * lens_r1 - lens_height / 2. * lens_height / 2.) - layer01; - double ztrans2 = lens_thickness / 2. + sqrt(lens_r2 * lens_r2 - lens_height / 2. * lens_height / 2.) - layer12; + double lens_min_thickness = 2.0 * mm; - Box gfbox("fbox", 0.5 * prism_short_edge, 0.5 * prism_width, 0.5 * lens_thickness); - Box gcbox("cbox", 0.5 * prism_short_edge, 0.5 * prism_width + 1 * mm, 0.5 * lens_thickness); + double ztrans1 = -lens_thickness / 2. - sqrt(lens_r1 * lens_r1 - lens_radius * lens_radius) + lens_min_thickness; + double ztrans2 = -lens_thickness / 2. - sqrt(lens_r2 * lens_r2 - lens_radius * lens_radius) + lens_min_thickness * 2; - Position tTrans1(0.5 * (prism_short_edge + lens_height), 0, lens_thickness - layer12); - Position tTrans0(-0.5 * (prism_short_edge + lens_height), 0, lens_thickness - layer12); - SubtractionSolid tubox("tubox", gfbox, gcbox, tTrans1); - SubtractionSolid gubox("gubox", tubox, gcbox, tTrans0); + Box lens_symm_box("lens_symm_box", 0.5 * prism_short_edge, 0.5 * lens_width, 0.5 * lens_thickness); + Volume Envelope_lens_vol("Envelope_lens_vol", lens_symm_box, desc.material("AirOptical")); - Tube gcylinder1("Cylinder1", 0, lens_r1, 0.5 * prism_width, 0 * deg, 360 * deg); - Tube gcylinder2("Cylinder2", 0, lens_r2, 0.5 * prism_width - 0.5 * mm, 0 * deg, 360 * deg); - Tube gcylinder1c("Cylinder1c", 0, lens_r1, 0.5 * prism_width + 0.5 * mm, 0 * deg, 360 * deg); - Tube gcylinder2c("Cylinder2c", 0, lens_r2, 0.5 * prism_width + 0.5 * mm, 0 * deg, 360 * deg); + Tube lens_symm_tube(0, lens_radius, 0.5 * lens_thickness); - IntersectionSolid lens_layer1_solid("lens_layer1_solid", gubox, gcylinder1, - Transform3D(RotationX(M_PI / 2.), Position(0, 0, ztrans1))); - SubtractionSolid gLenst("temp", gubox, gcylinder1c, Transform3D(RotationX(M_PI / 2.), Position(0, 0, ztrans1))); + Sphere lens_sphere1(0, lens_r1); + Sphere lens_sphere2(0, lens_r2); - IntersectionSolid lens_layer2_solid("lens_layer2_solid", gLenst, gcylinder2, - Transform3D(RotationX(M_PI / 2.), Position(0, 0, ztrans2))); - SubtractionSolid lens_layer3_solid("lens_layer3_solid", gLenst, gcylinder2c, - Transform3D(RotationX(M_PI / 2.), Position(0, 0, ztrans2))); + IntersectionSolid lens_box("lens_box", lens_symm_box, lens_symm_box, Position(0, 0, -lens_min_thickness * 2)); + IntersectionSolid lens_tube("lens_tube", lens_symm_tube, lens_symm_box, Position(0, 0, lens_min_thickness * 2)); + UnionSolid lens_box_tube("lens_box_tube", lens_box, lens_tube); + + IntersectionSolid lens_layer1_solid("lens_layer1_solid", lens_box_tube, lens_sphere1, Position(0, 0, -ztrans1)); + SubtractionSolid lens_layer23_solid("lens_layer23_solid", lens_box_tube, lens_sphere1, Position(0, 0, -ztrans1)); + + IntersectionSolid lens_layer2_solid("lens_layer2_solid", lens_layer23_solid, lens_sphere2, Position(0, 0, -ztrans2)); + SubtractionSolid lens_layer3_solid("lens_layer3_solid", lens_layer23_solid, lens_sphere2, Position(0, 0, -ztrans2)); Volume lens_layer1_vol("lens_layer1_vol", lens_layer1_solid, desc.material(xml_lens.attr(_Unicode(material1)))); @@ -162,10 +159,18 @@ static Ref_t createDetector(Detector& desc, xml_h e, SensitiveDetector sens) double lens_position_x = lens_shift; double lens_position_z = -0.5 * (bar_assm_length + lens_thickness); - Position lens_position(lens_position_x, 0, lens_position_z); - dirc_module.placeVolume(lens_layer1_vol, lens_position); - dirc_module.placeVolume(lens_layer2_vol, lens_position); - dirc_module.placeVolume(lens_layer3_vol, lens_position); + + for(int y_index = 0; y_index < bar_repeat_y; y_index++) + { + double lens_position_y = y_index*lens_width - 0.5*(prism_width - lens_width); + + Position lens_position(lens_position_x, lens_position_y, lens_position_z); + dirc_module.placeVolume(Envelope_lens_vol, lens_position); + } + + Envelope_lens_vol.placeVolume(lens_layer1_vol); + Envelope_lens_vol.placeVolume(lens_layer2_vol); + Envelope_lens_vol.placeVolume(lens_layer3_vol); // Prism construction Trap prism_trap = MakeTrap("prism_trap", prism_width, prism_length, prism_long_edge, prism_short_edge); @@ -176,7 +181,21 @@ static Ref_t createDetector(Detector& desc, xml_h e, SensitiveDetector sens) double prism_position_z = -0.5 * (bar_assm_length + prism_length) - lens_thickness; RotationX prism_rotation(M_PI / 2.); Position prism_position(prism_position_x, 0, prism_position_z); - dirc_module.placeVolume(prism_vol, Transform3D(prism_rotation, prism_position)); + + // Envelope for prism + mcp + + double Envelope_trap_width = prism_width + 1*mm; + double Envelope_trap_length = prism_length + 1*mm; // mcp thickness is 1 mm + double Envelope_trap_short_edge = prism_short_edge + 1*mm; + double Envelope_trap_long_edge = Envelope_trap_short_edge + Envelope_trap_length * tan(prism_angle); + + Trap Envelope_trap = MakeTrap("Envelope_trap", Envelope_trap_width, Envelope_trap_length, Envelope_trap_long_edge, Envelope_trap_short_edge); + Position Envelope_trap_position(prism_position_x, 0, prism_position_z - 0.5*mm); + + Volume Envelope_trap_vol("Envelope_trap_vol", Envelope_trap, desc.material("AirOptical")); + dirc_module.placeVolume(Envelope_trap_vol, Transform3D(prism_rotation, Envelope_trap_position)); + + Envelope_trap_vol.placeVolume(prism_vol, Position(0, 0.5*mm, 0)); // MCP variables xml_comp_t xml_mcp = xml_module.child(_Unicode(mcp)); @@ -189,10 +208,11 @@ static Ref_t createDetector(Detector& desc, xml_h e, SensitiveDetector sens) Volume mcp_vol("mcp_vol", mcp_box, desc.material(xml_mcp.materialStr())); mcp_vol.setVisAttributes(desc.visAttributes(xml_mcp.visStr())).setSensitiveDetector(sens); - double mcp_position_x = 0.5 * prism_long_edge - 0.5 * prism_short_edge + lens_shift; - double mcp_position_z = -0.5 * bar_assm_length - lens_thickness - prism_length - 0.5 * mcp_thickness; - Position mcp_position(mcp_position_x, 0, mcp_position_z); - dirc_module.placeVolume(mcp_vol, mcp_position); + double mcp_position_z = -0.5 * prism_length; + Position mcp_position(prism_position_x, mcp_position_z, 0); + RotationX mcp_rotation(-M_PI / 2.); + + Envelope_trap_vol.placeVolume(mcp_vol, Transform3D(mcp_rotation, mcp_position)); // Place modules const int module_repeat = xml_module.repeat(); From a76322423227e5c252eea4a6f96d8031df19dd92 Mon Sep 17 00:00:00 2001 From: Chao Peng Date: Thu, 4 May 2023 22:18:18 -0500 Subject: [PATCH 3/8] Update Geometry for Barrel EMCal (#422) ### Briefly, what does this PR introduce? Update the geometry for barrel ecal: Change geometry to 48 staves Change the readout grid to cover even distance in Delta Phi (see the picture below) - i.e., always divide stave (1/48) into 5 readout grids in one readout layer Add 3 cm of Aluminum at the back of the calo ### What kind of change does this PR introduce? - [ ] Bug fix (issue #__) - [ ] New feature (issue #__) - [ ] Documentation update - [x] Other: Geometry Update ### Please check if this PR fulfills the following: - [ ] Tests for the changes have been added - [ ] Documentation has been added / updated - [x] Changes have been communicated to collaborators ### Does this PR introduce breaking changes? What changes might users need to make to their code? No ### Does this PR change default behavior? No --------- Co-authored-by: Chao Peng Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- compact/definitions.xml | 2 +- compact/display.xml | 2 +- compact/display_detailed.xml | 2 +- compact/display_geoviewer.xml | 2 +- compact/ecal/barrel_interlayers.xml | 9 +- .../subdetector_tests/draw_bemc_scfi_grids.py | 9 +- src/BarrelCalorimeterInterlayers_geo.cpp | 198 +++++------------- 7 files changed, 75 insertions(+), 149 deletions(-) diff --git a/compact/definitions.xml b/compact/definitions.xml index 40fcef2a5b..4d0e5e99fe 100644 --- a/compact/definitions.xml +++ b/compact/definitions.xml @@ -513,7 +513,7 @@ Service gaps in FW direction (before endcapP ECAL) and BW direction (before endc ## Calorimeter Parameters - + diff --git a/compact/display.xml b/compact/display.xml index 4ebcbe9f93..7b6a19b457 100644 --- a/compact/display.xml +++ b/compact/display.xml @@ -66,10 +66,10 @@ - + diff --git a/compact/display_detailed.xml b/compact/display_detailed.xml index 1fb9e874c4..712d5026a6 100644 --- a/compact/display_detailed.xml +++ b/compact/display_detailed.xml @@ -60,7 +60,7 @@ - + diff --git a/compact/display_geoviewer.xml b/compact/display_geoviewer.xml index 51fda1130d..1c9abe7f20 100644 --- a/compact/display_geoviewer.xml +++ b/compact/display_geoviewer.xml @@ -59,7 +59,7 @@ - + diff --git a/compact/ecal/barrel_interlayers.xml b/compact/ecal/barrel_interlayers.xml index cf28c16fb4..5596242d52 100644 --- a/compact/ecal/barrel_interlayers.xml +++ b/compact/ecal/barrel_interlayers.xml @@ -27,7 +27,7 @@ - + @@ -149,7 +149,9 @@ space_before="EcalBarrel_ImagingLayerThickness + EcalBarrel_SpaceBetween/2."> + diff --git a/scripts/subdetector_tests/draw_bemc_scfi_grids.py b/scripts/subdetector_tests/draw_bemc_scfi_grids.py index 3fa29aaa4c..5b8bd62e11 100644 --- a/scripts/subdetector_tests/draw_bemc_scfi_grids.py +++ b/scripts/subdetector_tests/draw_bemc_scfi_grids.py @@ -129,7 +129,11 @@ def get_grid_fibers(det_elem, vol_man, id_conv, id_dict): ) parser.add_argument( '--no-marker', action='store_true', - help='Switch to draw a marker for grid center or not' + help='Switch on to not draw a marker for each grid\'s center', + ) + parser.add_argument( + '--no-fiber-edge', action='store_true', + help='Switch on to not draw fiber edge, might be helpful for a crowded plot.', ) args = parser.parse_args() @@ -181,7 +185,8 @@ def get_grid_fibers(det_elem, vol_man, id_conv, id_dict): patches = [] for fi in fibers: patches.append(Circle((fi[0], fi[1]), fi[3])) - p = PatchCollection(patches, alpha=0.6, facecolors=(c,), edgecolors=('k',)) + ec = 'k' if not args.no_fiber_edge else c + p = PatchCollection(patches, alpha=0.6, facecolors=(c,), edgecolors=(ec,)) if not args.no_marker: ax.plot(gr_pos[0], gr_pos[1], marker='P', mfc=c, mec='k', ms=9, label='grid {}'.format(ids['grid'])) ax.add_collection(p) diff --git a/src/BarrelCalorimeterInterlayers_geo.cpp b/src/BarrelCalorimeterInterlayers_geo.cpp index 8f8ed5fd1e..da06acfbbf 100644 --- a/src/BarrelCalorimeterInterlayers_geo.cpp +++ b/src/BarrelCalorimeterInterlayers_geo.cpp @@ -50,8 +50,7 @@ struct FiberGrid { vector fiberPositions(double r, double sx, double sz, double trx, double trz, double phi, bool shift_first = false, double stol = 1e-2); -std::pair getNdivisions(double x, double z, double dx, double dz); -vector gridPoints(int div_x, int div_z, double x, double z, double phi); +vector gridPoints(int div_n_phi, double div_dr, double x, double z, double phi); // geometry helpers void buildFibers(Detector& desc, SensitiveDetector& sens, Volume& mother, int layer_nunber, xml_comp_t x_fiber, @@ -187,9 +186,9 @@ static Ref_t create_detector(Detector& desc, xml_h e, SensitiveDetector sens) if (x_det.hasChild(_U(staves))) { xml_comp_t x_staves = x_det.staves(); mod_vol.setVisAttributes(desc.visAttributes(x_staves.visStr())); - if (x_staves.hasChild(_U(support))) { - buildSupport(desc, mod_vol, x_staves.child(_U(support)), {inner_r, l_pos_z, x_dim.z(), hphi}); - } + } + if (x_det.hasChild(_U(support))) { + buildSupport(desc, mod_vol, x_det.child(_U(support)), {inner_r, l_pos_z, x_dim.z(), hphi}); } // Set envelope volume attributes. @@ -205,6 +204,8 @@ void buildFibers(Detector& desc, SensitiveDetector& sens, Volume& s_vol, int lay double f_cladding_thickness = getAttrOrDefault(x_fiber, _Unicode(cladding_thickness), 0.0 * cm); double f_spacing_x = getAttrOrDefault(x_fiber, _Unicode(spacing_x), 0.122 * cm); double f_spacing_z = getAttrOrDefault(x_fiber, _Unicode(spacing_z), 0.134 * cm); + int grid_n_phi = getAttrOrDefault(x_fiber, _Unicode(grid_n_phi), 5); + double grid_dr = getAttrOrDefault(x_fiber, _Unicode(grid_dr), 2.0*cm); std::string f_id_grid = getAttrOrDefault(x_fiber, _Unicode(identifier_grid), "grid"); std::string f_id_fiber = getAttrOrDefault(x_fiber, _Unicode(identifier_fiber), "fiber"); @@ -227,11 +228,10 @@ void buildFibers(Detector& desc, SensitiveDetector& sens, Volume& s_vol, int lay f_vol_core.setAttributes(desc, x_fiber.regionStr(), x_fiber.limitsStr(), x_fiber.visStr()); - // Calculate number of divisions - auto grid_div = getNdivisions(s_trd_x1, s_thick, 2.0 * cm, 2.0 * cm); - // Calculate polygonal grid coordinates (vertices) - auto grids = gridPoints(grid_div.first, grid_div.second, s_trd_x1, s_thick, hphi); - vector f_id_count(grid_div.first * grid_div.second, 0); + // calculate polygonal grid coordinates (vertices) + auto grids = gridPoints(grid_n_phi, grid_dr, s_trd_x1, s_thick, hphi); + vector f_id_count(grids.size(), 0); + // use layer_number % 2 to add correct shifts for the adjacent fibers at layer boundary auto f_pos = fiberPositions(f_radius, f_spacing_x, f_spacing_z, s_trd_x1, s_thick, hphi, (layer_number % 2 == 0)); // a helper struct to speed up searching struct Fiber { @@ -279,7 +279,7 @@ void buildFibers(Detector& desc, SensitiveDetector& sens, Volume& s_vol, int lay // fiber is along y-axis of the layer volume, so grids are arranged on X-Z plane Transform3D gr_tr(RotationZYX(0., 0., M_PI*0.5), Position(gr.mean_centroid.x(), 0., gr.mean_centroid.y())); auto grid_phv = s_vol.placeVolume(grid_vol, gr_tr); - grid_phv.addPhysVolID(f_id_grid, gr.ix + gr.iy * grid_div.first + 1); + grid_phv.addPhysVolID(f_id_grid, gr.ix + gr.iy * grid_n_phi + 1); grid_vol.ptr()->Voxelize(""); } } @@ -297,93 +297,22 @@ void buildFibers(Detector& desc, SensitiveDetector& sens, Volume& s_vol, int lay */ } -// DAWN view seems to have some issue with overlapping solids even if they were unions -// The support is now built without overlapping +// simple aluminum sheet cover +// dimensions: (inner r, position in z, length, phi) void buildSupport(Detector& desc, Volume& mod_vol, xml_comp_t x_support, const std::tuple& dimensions) { - auto [inner_r, l_pos_z, stave_length, hphi] = dimensions; - - double support_thickness = getAttrOrDefault(x_support, _Unicode(thickness), 5. * cm); - double beam_thickness = getAttrOrDefault(x_support, _Unicode(beam_thickness), support_thickness / 4.); - // sanity check - if (beam_thickness > support_thickness / 3.) { - std::cerr << Form("beam_thickness (%.2f) cannot be greater than support_thickness/3 (%.2f), shrink it to fit", - beam_thickness, support_thickness / 3.) - << std::endl; - beam_thickness = support_thickness / 3.; - } - Assembly env_vol("support_envelope"); - double trd_y = stave_length / 2.; - double trd_x1_support = std::tan(hphi) * l_pos_z; - // FIXME trd_x2_support is filled but unused - // double trd_x2_support = std::tan(hphi) * (l_pos_z + support_thickness); - - double grid_size = getAttrOrDefault(x_support, _Unicode(grid_size), 25. * cm); - int n_cross_supports = std::floor(trd_y - beam_thickness) / grid_size; - // number of "beams" running the length of the stave. - // @TODO make it configurable - int n_beams = getAttrOrDefault(x_support, _Unicode(n_beams), 3); - ; - double beam_width = 2. * trd_x1_support / (n_beams + 1); // quick hack to make some gap between T beams - double beam_gap = getAttrOrDefault(x_support, _Unicode(beam_gap), 3. * cm); - - // build T-shape beam - double beam_space_x = beam_width + beam_gap; - [[maybe_unused]] double beam_space_z = support_thickness - beam_thickness; - double cross_thickness = support_thickness - beam_thickness; - double beam_pos_z = beam_thickness / 2.; - [[maybe_unused]] double beam_center_z = support_thickness / 2. - beam_pos_z; - - Box beam_vert_s(beam_thickness / 2., trd_y, cross_thickness / 2.); - Box beam_hori_s(beam_width / 2., trd_y, beam_thickness / 2.); - UnionSolid T_beam_s(beam_hori_s, beam_vert_s, Position(0., 0., support_thickness / 2.)); - Volume H_beam_vol("H_beam", T_beam_s, desc.material(x_support.materialStr())); - H_beam_vol.setVisAttributes(desc, x_support.visStr()); - // place H beams first - double beam_start_x = -(n_beams - 1) * (beam_width + beam_gap) / 2.; - for (int i = 0; i < n_beams; ++i) { - Position beam_pos(beam_start_x + i * (beam_width + beam_gap), 0., -support_thickness / 2. + beam_pos_z); - env_vol.placeVolume(H_beam_vol, beam_pos); - } - - // place central crossing beams that connects the H beams - double cross_x = beam_space_x - beam_thickness; - Box cross_s(cross_x / 2., beam_thickness / 2., cross_thickness / 2.); - Volume cross_vol("cross_center_beam", cross_s, desc.material(x_support.materialStr())); - cross_vol.setVisAttributes(desc, x_support.visStr()); - for (int i = 0; i < n_beams - 1; ++i) { - env_vol.placeVolume(cross_vol, Position(beam_start_x + beam_space_x * (i + 0.5), 0., beam_pos_z)); - for (int j = 1; j < n_cross_supports; j++) { - env_vol.placeVolume(cross_vol, Position(beam_start_x + beam_space_x * (i + 0.5), -j * grid_size, beam_pos_z)); - env_vol.placeVolume(cross_vol, Position(beam_start_x + beam_space_x * (i + 0.5), j * grid_size, beam_pos_z)); - } - } - - // place edge crossing beams that connects the neighbour support - // @TODO: connection part is still using boolean volumes, maybe problematic to DAWN - double cross_edge_x = trd_x1_support + beam_start_x - beam_thickness / 2.; - double cross_trd_x1 = cross_edge_x + std::tan(hphi) * beam_thickness; - double cross_trd_x2 = cross_trd_x1 + 2. * std::tan(hphi) * cross_thickness; - double edge_pos_x = beam_start_x - cross_trd_x1 / 2. - beam_thickness / 2; - Trapezoid cross_s2_trd(cross_trd_x1 / 2., cross_trd_x2 / 2., beam_thickness / 2., beam_thickness / 2., - cross_thickness / 2.); - Box cross_s2_box((cross_trd_x2 - cross_trd_x1) / 4., beam_thickness / 2., cross_thickness / 2.); - SubtractionSolid cross_s2(cross_s2_trd, cross_s2_box, Position((cross_trd_x2 + cross_trd_x1) / 4., 0., 0.)); - Volume cross_vol2("cross_edge_beam", cross_s2, desc.material(x_support.materialStr())); - cross_vol2.setVisAttributes(desc, x_support.visStr()); - env_vol.placeVolume(cross_vol2, Position(edge_pos_x, 0., beam_pos_z)); - env_vol.placeVolume(cross_vol2, Transform3D(Translation3D(-edge_pos_x, 0., beam_pos_z) * RotationZ(M_PI))); - for (int j = 1; j < n_cross_supports; j++) { - env_vol.placeVolume(cross_vol2, Position(edge_pos_x, -j * grid_size, beam_pos_z)); - env_vol.placeVolume(cross_vol2, Position(edge_pos_x, j * grid_size, beam_pos_z)); - env_vol.placeVolume(cross_vol2, - Transform3D(Translation3D(-edge_pos_x, -j * grid_size, beam_pos_z) * RotationZ(M_PI))); - env_vol.placeVolume(cross_vol2, - Transform3D(Translation3D(-edge_pos_x, j * grid_size, beam_pos_z) * RotationZ(M_PI))); - } - - mod_vol.placeVolume(env_vol, Position(0.0, 0.0, l_pos_z + support_thickness / 2.)); + auto [inner_r, pos_z, stave_length, hphi] = dimensions; + double support_thickness = getAttrOrDefault(x_support, _Unicode(thickness), 3.*cm); + auto material = desc.material(x_support.materialStr()); + double trd_y = stave_length / 2.; + double trd_x1_support = std::tan(hphi) * pos_z; + double trd_x2_support = std::tan(hphi) * (pos_z + support_thickness); + + Trapezoid s_shape(trd_x1_support, trd_x2_support, trd_y, trd_y, support_thickness / 2.); + Volume s_vol("support_layer", s_shape, material); + s_vol.setVisAttributes(desc.visAttributes(x_support.visStr())); + mod_vol.placeVolume(s_vol, Position(0.0, 0.0, pos_z + support_thickness / 2.)); } // Fill fiber lattice into trapezoid starting from position (0,0) in x-z coordinate system @@ -422,13 +351,12 @@ vector fiberPositions(double r, double sx, double sz, double trx, double return positions; } -// Calculate number of divisions for the readout grid for the fiber layers -std::pair getNdivisions(double x, double z, double dx, double dz) +// Determine the number of divisions for the readout grid for the fiber layers +// Calculate dimensions of the polygonal grid +vector gridPoints(int div_n_phi, double div_dr, double trd_x1, double height, double phi) { - // x and z defined as in vector fiberPositions - // dx, dz - size of the grid in x and z we want to get close to with the polygons - // See also descripltion when the function is called - + /* + // TODO: move this test to xml file double SiPMsize = 13.0 * mm; double grid_min = SiPMsize + 3.0 * mm; @@ -439,56 +367,44 @@ std::pair getNdivisions(double x, double z, double dx, double dz) if (dx < grid_min) { dx = grid_min; } + */ + // number of divisions + int nph = div_n_phi; + int nr = floor(height / div_dr); + if (nr == 0) { + nr++; + } - int nfit_cells_z = floor(z / dz); - int n_cells_z = nfit_cells_z; - - if (nfit_cells_z == 0) - n_cells_z++; - - int nfit_cells_x = floor((2 * x) / dx); - int n_cells_x = nfit_cells_x; - - if (nfit_cells_x == 0) - n_cells_x++; - - return std::make_pair(n_cells_x, n_cells_z); -} - -// Calculate dimensions of the polygonal grid in the cartesian coordinate system x-z -vector gridPoints(int div_x, int div_z, double x, double z, double phi) -{ - // x, z and phi defined as in vector fiberPositions - // div_x, div_z - number of divisions in x and z + // grid vertices vector results; - double dz = z / div_z; + double dr = height / nr; - for (int iz = 0; iz < div_z + 1; iz++) { - for (int ix = 0; ix < div_x + 1; ix++) { - double A_z = -z / 2 + iz * dz; - double B_z = -z / 2 + (iz + 1) * dz; + for (int ir = 0; ir <= nr; ir++) { + for (int iph = 0; iph <= nph; iph++) { + double A_y = -height / 2. + ir * dr; + double B_y = -height / 2. + (ir + 1) * dr; - double len_x_for_z = 2 * (x + iz * dz * tan(phi)); - double len_x_for_z_plus_1 = 2 * (x + (iz + 1) * dz * tan(phi)); + double botl_dr = 2 * (trd_x1 + ir * dr * tan(phi)); + double topl_dr = 2 * (trd_x1 + (ir + 1) * dr * tan(phi)); - double dx_for_z = len_x_for_z / div_x; - double dx_for_z_plus_1 = len_x_for_z_plus_1 / div_x; + double botl_dph_dr = botl_dr / nph; + double topl_dph_dr = topl_dr / nph; - double A_x = -len_x_for_z / 2. + ix * dx_for_z; - double B_x = -len_x_for_z_plus_1 / 2. + ix * dx_for_z_plus_1; + double A_x = -botl_dr / 2. + iph * botl_dph_dr; + double B_x = -topl_dr / 2. + iph * topl_dph_dr; - double C_z = B_z; - double D_z = A_z; - double C_x = B_x + dx_for_z_plus_1; - double D_x = A_x + dx_for_z; + double C_y = B_y; + double D_y = A_y; + double C_x = B_x + topl_dph_dr; + double D_x = A_x + botl_dph_dr; - auto A = Point(A_x, A_z); - auto B = Point(B_x, B_z); - auto C = Point(C_x, C_z); - auto D = Point(D_x, D_z); + auto A = Point(A_x, A_y); + auto B = Point(B_x, B_y); + auto C = Point(C_x, C_y); + auto D = Point(D_x, D_y); // vertex points filled in the clock-wise direction - results.emplace_back(FiberGrid(ix, iz, {A, B, C, D})); + results.emplace_back(FiberGrid(iph, ir, {A, B, C, D})); } } From 8d2c50081146390402f4d7178d98b196dcb207d7 Mon Sep 17 00:00:00 2001 From: Dmitry Kalinkin Date: Sat, 6 May 2023 22:52:32 -0400 Subject: [PATCH 4/8] BarrelCalorimeterInterlayers: embed fiber core volume into cladding (#419) This reduces the number of volumes to be placed and processed. --- src/BarrelCalorimeterInterlayers_geo.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/BarrelCalorimeterInterlayers_geo.cpp b/src/BarrelCalorimeterInterlayers_geo.cpp index da06acfbbf..8706fc0a3a 100644 --- a/src/BarrelCalorimeterInterlayers_geo.cpp +++ b/src/BarrelCalorimeterInterlayers_geo.cpp @@ -218,7 +218,7 @@ void buildFibers(Detector& desc, SensitiveDetector& sens, Volume& s_vol, int lay // fiber and its cladding double f_radius_core = f_radius - f_cladding_thickness; - Tube f_tube_clad(f_radius_core, f_radius, s_length); + Tube f_tube_clad(0, f_radius, s_length); Volume f_vol_clad("fiber_vol", f_tube_clad, desc.material(x_fiber.materialStr())); Tube f_tube_core(0, f_radius_core, s_length); Volume f_vol_core("fiber_core_vol", f_tube_core, desc.material(x_fiber.materialStr())); @@ -226,6 +226,7 @@ void buildFibers(Detector& desc, SensitiveDetector& sens, Volume& s_vol, int lay f_vol_core.setSensitiveDetector(sens); } f_vol_core.setAttributes(desc, x_fiber.regionStr(), x_fiber.limitsStr(), x_fiber.visStr()); + f_vol_clad.placeVolume(f_vol_core); // calculate polygonal grid coordinates (vertices) @@ -267,9 +268,8 @@ void buildFibers(Detector& desc, SensitiveDetector& sens, Volume& s_vol, int lay // place fiber in grid auto p = fi.pos - gr.mean_centroid; - auto core_phv = grid_vol.placeVolume(f_vol_core, Position(p.x(), p.y(), 0.)); - core_phv.addPhysVolID(f_id_fiber, f_id); - grid_vol.placeVolume(f_vol_clad, Position(p.x(), p.y(), 0.)); + auto clad_phv = grid_vol.placeVolume(f_vol_clad, Position(p.x(), p.y(), 0.)); + clad_phv.addPhysVolID(f_id_fiber, f_id); fi.assigned = true; f_id ++; } From 00d59f260572c4abdfafbdf9812426d4c9439b0b Mon Sep 17 00:00:00 2001 From: Jakub Ceska <53567935+ceskajak@users.noreply.github.com> Date: Mon, 8 May 2023 18:54:10 -0400 Subject: [PATCH 5/8] Forward electron beampipe (#386) ### Briefly, what does this PR introduce? Added forward electron beampipe and required source file. Added beampipe to beampipe section of the template builder jinja2. Forward electron beampipe is essential for running background simulations. ### What kind of change does this PR introduce? - [x] New feature Adds forward electron beampipe. ### Please check if this PR fulfills the following: - [ ] Tests for the changes have been added - [ ] Documentation has been added / updated - [x] Changes have been communicated to collaborators ### Does this PR introduce breaking changes? What changes might users need to make to their code? No changes to default behavior expected. Geometry now includes said beampipe segment and its magnets. The clearances have been checked and no conflict with forward detector assembly found. ### Does this PR change default behavior? Forward electron beamline now present in .xml files, as it is grouped together with central beampipe in the jinja2 template maker. --------- Co-authored-by: ceskajak Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Wouter Deconinck Co-authored-by: Christopher Dilks Co-authored-by: Dmitry Kalinkin --- compact/central_beampipe.xml | 3 +- compact/far_forward.xml | 1 + compact/far_forward/definitions.xml | 4 +- compact/far_forward/electron_beamline.xml | 112 ++++++++++++++++++++++ compact/far_forward/ion_beamline.xml | 13 --- 5 files changed, 117 insertions(+), 16 deletions(-) create mode 100644 compact/far_forward/electron_beamline.xml diff --git a/compact/central_beampipe.xml b/compact/central_beampipe.xml index d611b1fb9a..54d5dc0d84 100644 --- a/compact/central_beampipe.xml +++ b/compact/central_beampipe.xml @@ -62,7 +62,8 @@ - + + diff --git a/compact/far_forward.xml b/compact/far_forward.xml index aca73425ab..bab9440722 100644 --- a/compact/far_forward.xml +++ b/compact/far_forward.xml @@ -5,6 +5,7 @@ + diff --git a/compact/far_forward/definitions.xml b/compact/far_forward/definitions.xml index c930874818..2d106024c1 100644 --- a/compact/far_forward/definitions.xml +++ b/compact/far_forward/definitions.xml @@ -62,8 +62,8 @@ - - + + diff --git a/compact/far_forward/electron_beamline.xml b/compact/far_forward/electron_beamline.xml new file mode 100644 index 0000000000..88f4642019 --- /dev/null +++ b/compact/far_forward/electron_beamline.xml @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + !--unchecked-- + + + + + + + + + + + + + + + + !--unchecked-- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/compact/far_forward/ion_beamline.xml b/compact/far_forward/ion_beamline.xml index bfd7e4efd9..5ca8bcd706 100644 --- a/compact/far_forward/ion_beamline.xml +++ b/compact/far_forward/ion_beamline.xml @@ -69,19 +69,6 @@ - - - - - - - - - - - - - From 11b9cd4ef2da504b8c115b22db3b63a548288283 Mon Sep 17 00:00:00 2001 From: mariakzurek <33816222+mariakzurek@users.noreply.github.com> Date: Tue, 9 May 2023 21:25:04 -0500 Subject: [PATCH 6/8] draw_bemc_scfi_grids.py: fix grid plotting script for SciFi/Pb (#425) This PR fixes a bug in the SciFi/Pb plotting script. After https://github.com/eic/epic/commit/8d2c50081146390402f4d7178d98b196dcb207d7 the daughter of the grid is `fiber` only, not `fiber_core`. Because of this issue fibers were not plotted correctly. --- scripts/subdetector_tests/draw_bemc_scfi_grids.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/subdetector_tests/draw_bemc_scfi_grids.py b/scripts/subdetector_tests/draw_bemc_scfi_grids.py index 5b8bd62e11..59ca58e7b5 100644 --- a/scripts/subdetector_tests/draw_bemc_scfi_grids.py +++ b/scripts/subdetector_tests/draw_bemc_scfi_grids.py @@ -61,7 +61,7 @@ def get_grid_fibers(det_elem, vol_man, id_conv, id_dict): for i in np.arange(gnode.GetNdaughters()): fnode = gnode.GetDaughter(int(i)) # NOTE, this is defined in geometry plugin, fiber_core is the only wanted sensitive detector - if 'fiber_core' not in fnode.GetName(): + if 'fiber' not in fnode.GetName(): continue fpos = np.array([0., 0., 0.]) gpos = np.array([0., 0., 0.]) From e62fd39c1ecabfea806d5b9a964f973efe02c4b3 Mon Sep 17 00:00:00 2001 From: Dhevan Gangadharan <43478603+dhevang@users.noreply.github.com> Date: Fri, 12 May 2023 16:18:59 -0500 Subject: [PATCH 7/8] Change Lumi Pair Spectrometer Tracker and CAL parameters (#424) ### Briefly, what does this PR introduce? Change a few geometry parameters for the lumi pair spectrometer trackers and CAL. ### What kind of change does this PR introduce? - [ ] Bug fix (issue #__) - [ ] New feature (issue #__) - [ ] Documentation update - [x] Other: Change detector parameters to more realistic settings. ### Please check if this PR fulfills the following: - [ ] Tests for the changes have been added - [ ] Documentation has been added / updated - [ ] Changes have been communicated to collaborators ### Does this PR introduce breaking changes? What changes might users need to make to their code? ### Does this PR change default behavior? --------- Co-authored-by: Wouter Deconinck --- compact/far_backward/definitions.xml | 7 +++---- compact/far_backward/lumi/spec_homo_cal.xml | 2 +- compact/far_backward/lumi/spec_tracker.xml | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/compact/far_backward/definitions.xml b/compact/far_backward/definitions.xml index fb57e60f5e..fd2e29559b 100644 --- a/compact/far_backward/definitions.xml +++ b/compact/far_backward/definitions.xml @@ -256,8 +256,8 @@ - + @@ -269,10 +269,9 @@ - - - + + diff --git a/compact/far_backward/lumi/spec_homo_cal.xml b/compact/far_backward/lumi/spec_homo_cal.xml index bbd475b446..218916cb18 100644 --- a/compact/far_backward/lumi/spec_homo_cal.xml +++ b/compact/far_backward/lumi/spec_homo_cal.xml @@ -5,7 +5,7 @@ - + diff --git a/compact/far_backward/lumi/spec_tracker.xml b/compact/far_backward/lumi/spec_tracker.xml index 7e62235491..9245aff567 100644 --- a/compact/far_backward/lumi/spec_tracker.xml +++ b/compact/far_backward/lumi/spec_tracker.xml @@ -67,7 +67,7 @@ - + system:8,sector:8,module:8,x:32:-16,y:-16 From b9c705593b978b5d847bc7e128c8015cfa72ebbf Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Sat, 13 May 2023 00:44:01 -0400 Subject: [PATCH 8/8] feat: define example world limit set and region (#429) ### Briefly, what does this PR introduce? Recent DD4hep supports defining a world limit set and region, which extends to the full simulation. This doesn't introduce any limits, but demonstrates how to do it. This can also be extended to individual detectors. ### What kind of change does this PR introduce? - [ ] Bug fix (issue #__) - [ ] New feature (issue #__) - [x] Documentation update - [ ] Other: __ ### Please check if this PR fulfills the following: - [ ] Tests for the changes have been added - [x] Documentation has been added / updated - [ ] Changes have been communicated to collaborators ### Does this PR introduce breaking changes? What changes might users need to make to their code? No. ### Does this PR change default behavior? No. --- templates/epic.xml.jinja2 | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/templates/epic.xml.jinja2 b/templates/epic.xml.jinja2 index ffbf78a482..742196c5f4 100644 --- a/templates/epic.xml.jinja2 +++ b/templates/epic.xml.jinja2 @@ -59,7 +59,9 @@ - + + + @@ -71,6 +73,12 @@ + + + + + + @@ -83,6 +91,8 @@ + +