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/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/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
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 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
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/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 @@
/>
diff --git a/scripts/subdetector_tests/draw_bemc_scfi_grids.py b/scripts/subdetector_tests/draw_bemc_scfi_grids.py
index 3fa29aaa4c..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.])
@@ -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..8706fc0a3a 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");
@@ -217,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()));
@@ -225,13 +226,13 @@ 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 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 {
@@ -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 ++;
}
@@ -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}));
}
}
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();
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 @@
+
+