SHiP Geometry
SHiP experiment geometry implementation using GeoModel.
Loading...
Searching...
No Matches
CalorimeterConstants.h
Go to the documentation of this file.
1// SPDX-License-Identifier: LGPL-3.0-or-later
2// Copyright (C) CERN for the benefit of the SHiP Collaboration
3
4#pragma once
5
6#include <array>
7#include <span>
8
17
19enum class LayerCode {
20 WidePVT_H,
21 WidePVT_V,
22 ThinPS_H,
23 ThinPS_V,
26 Absorber,
27 AirGap,
28};
29
30// ── Module geometry (mm) ────────────────────────────────────────────────
31inline constexpr double kPlateXY = 2160.0;
32inline constexpr double kLeadThickness = 3.0;
33inline constexpr double kScintThickness = 10.0;
34inline constexpr double kHplThickness = 10.0;
35inline constexpr double kFiberDiameter = 1.2;
36inline constexpr double kFiberCoreDiameter = 1.0;
37inline constexpr double kIronThickness = 170.0;
38
40inline constexpr double kAirGap = 1000.0;
42inline constexpr double kGapEcalHcal = 100.0;
43
44// Bar pitch (physical constant, independent of plate size)
45inline constexpr double kWidePVTBarPitch = 60.0;
46inline constexpr double kThinPSBarPitch = 10.0;
47
48// Module tiling: modules touch (pitch = plate size)
49inline constexpr int kModuleNX = 2;
50inline constexpr int kModuleNY = 3;
51inline constexpr double kModulePitchX = kPlateXY;
52inline constexpr double kModulePitchY = kPlateXY;
53
54// ── Layer sequences ─────────────────────────────────────────────────────
55//
56// The `using enum` is confined to each initialiser: at namespace scope in a
57// public header it would make Absorber, AirGap, WidePVT_H ... visible
58// unqualified throughout SHiPGeometry::Calo for every includer, which is most
59// of what enum class is for.
60
84
86inline constexpr auto kHcalLayers = [] {
87 using enum LayerCode;
88 return std::array{
91 };
92}();
93
94// ── Fixed container envelope ────────────────────────────────────────────
95// These match the SHiP subsystem envelope from subsystem_envelopes.csv
96// and must not change — tests and the consistency check depend on them.
97inline constexpr double kContainerHalfX = 3000.0; // 3.00 m
98inline constexpr double kContainerHalfY = 3500.0; // 3.50 m
99inline constexpr double kContainerHalfZ = 1450.0; // 1.45 m
100
101// ── Derived quantities ──────────────────────────────────────────────────
102
105constexpr double layerThickness(LayerCode code, double absorberThickness) {
106 using enum LayerCode;
107 switch (code) {
108 case Absorber:
109 return absorberThickness;
110 case WidePVT_H:
111 case WidePVT_V:
112 case ThinPS_H:
113 case ThinPS_V:
114 return kScintThickness;
115 case FibreHPL_Y:
116 case FibreHPL_X:
117 return kHplThickness;
118 case AirGap:
119 return kAirGap;
120 }
121 return 0.0; // unreachable: all enumerators covered (-Wswitch)
122}
123
125constexpr double sectionZ(std::span<const LayerCode> codes, double absorberThickness) {
126 double z = 0.0;
127 for (LayerCode code : codes)
128 z += layerThickness(code, absorberThickness);
129 return z;
130}
131
133inline constexpr double kTotalStackZ =
135
140constexpr int sectionVolumeCount(std::span<const LayerCode> codes) {
141 using enum LayerCode;
142 int n = 0;
143 for (LayerCode code : codes)
144 n += code == AirGap ? 0 : 1;
145 return n;
146}
147
149inline constexpr int kVolsPerModule =
151
153inline constexpr int kWidePVTBarCount = static_cast<int>(kPlateXY / kWidePVTBarPitch);
154inline constexpr int kThinPSBarCount = static_cast<int>(kPlateXY / kThinPSBarPitch);
155
156// ── Compile-time validation ──────────────────────────────────────────────
157static_assert(!kEcalLayers.empty() && !kHcalLayers.empty());
158static_assert(kEcalLayers.size() == 89, "transcription guard: 89 entries in the ECAL sequence");
159static_assert(kModuleNX > 0 && kModuleNY > 0);
160static_assert(kFiberCoreDiameter > 0.0 && kFiberCoreDiameter <= kFiberDiameter);
162 "plate size must be a whole number of wide PVT bars");
163static_assert(kThinPSBarCount * kThinPSBarPitch == kPlateXY,
164 "plate size must be a whole number of thin PS bars");
165static_assert(kTotalStackZ <= 2.0 * kContainerHalfZ, "layer stack exceeds the container in Z");
166static_assert(0.5 * kPlateXY + 0.5 * (kModuleNX - 1) * kModulePitchX <= kContainerHalfX,
167 "module array exceeds the container in X");
168static_assert(0.5 * kPlateXY + 0.5 * (kModuleNY - 1) * kModulePitchY <= kContainerHalfY,
169 "module array exceeds the container in Y");
170
171} // namespace SHiPGeometry::Calo
Compile-time parameters of the SHiP calorimeter geometry.
Definition CalorimeterConstants.h:16
constexpr double kModulePitchX
Definition CalorimeterConstants.h:51
constexpr double sectionZ(std::span< const LayerCode > codes, double absorberThickness)
Z extent of one calorimeter section (mm).
Definition CalorimeterConstants.h:125
LayerCode
Layer types used in the ECAL/HCAL layer sequences.
Definition CalorimeterConstants.h:19
@ FibreHPL_X
HPL fibre layer, fibres along X.
@ ThinPS_H
Thin PS bar layer, bars along X (H orientation)
@ WidePVT_V
Wide PVT bar layer, bars along Y (V orientation)
@ WidePVT_H
Wide PVT bar layer, bars along X (H orientation)
@ Absorber
Absorber plate (Lead in ECAL, Iron in HCAL)
@ FibreHPL_Y
HPL fibre layer, fibres along Y.
@ ThinPS_V
Thin PS bar layer, bars along Y (V orientation)
@ AirGap
Air gap (no volume, just advances z cursor)
constexpr int kModuleNX
Definition CalorimeterConstants.h:49
constexpr double kContainerHalfY
Definition CalorimeterConstants.h:98
constexpr int kVolsPerModule
Child volumes one module contributes to the container.
Definition CalorimeterConstants.h:149
constexpr double kLeadThickness
Definition CalorimeterConstants.h:32
constexpr auto kHcalLayers
HCAL layer sequence (Absorber means iron here rather than lead).
Definition CalorimeterConstants.h:86
constexpr double kFiberCoreDiameter
Definition CalorimeterConstants.h:36
constexpr auto kEcalLayers
ECAL layer sequence.
Definition CalorimeterConstants.h:62
constexpr int sectionVolumeCount(std::span< const LayerCode > codes)
Child volumes one section contributes to the container, per module.
Definition CalorimeterConstants.h:140
constexpr double layerThickness(LayerCode code, double absorberThickness)
Z advance of one layer of the given type (mm).
Definition CalorimeterConstants.h:105
constexpr double kScintThickness
Definition CalorimeterConstants.h:33
constexpr double kGapEcalHcal
Gap between the ECAL and HCAL stacks (mm).
Definition CalorimeterConstants.h:42
constexpr double kFiberDiameter
Definition CalorimeterConstants.h:35
constexpr double kTotalStackZ
Total Z extent of one ECAL+gap+HCAL stack (mm).
Definition CalorimeterConstants.h:133
constexpr int kModuleNY
Definition CalorimeterConstants.h:50
constexpr int kWidePVTBarCount
Bars per layer, from the plate size and the bar pitch.
Definition CalorimeterConstants.h:153
constexpr double kThinPSBarPitch
Definition CalorimeterConstants.h:46
constexpr double kIronThickness
Definition CalorimeterConstants.h:37
constexpr double kContainerHalfX
Definition CalorimeterConstants.h:97
constexpr double kAirGap
Air gap within the ECAL layer sequence (mm).
Definition CalorimeterConstants.h:40
constexpr double kContainerHalfZ
Definition CalorimeterConstants.h:99
constexpr double kHplThickness
Definition CalorimeterConstants.h:34
constexpr int kThinPSBarCount
Definition CalorimeterConstants.h:154
constexpr double kPlateXY
Definition CalorimeterConstants.h:31
constexpr double kModulePitchY
Definition CalorimeterConstants.h:52
constexpr double kWidePVTBarPitch
Definition CalorimeterConstants.h:45