Belle II Software development
GeoCDCCreator.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#include <cdc/geometry/GeoCDCCreator.h>
10#include <cdc/geometry/CDCGeometryPar.h>
11#include <cdc/geometry/CDCGeoControlPar.h>
12#include <cdc/simulation/CDCSimControlPar.h>
13#include <cdc/simulation/CDCSensitiveDetector.h>
14#include <simulation/background/BkgSensitiveDetector.h>
15
16#include <geometry/CreatorFactory.h>
17#include <geometry/Materials.h>
18
19#include <cmath>
20#include <boost/format.hpp>
21
22#include <G4Material.hh>
23#include <G4Box.hh>
24#include <G4Tubs.hh>
25#include <G4Torus.hh>
26#include <G4Trd.hh>
27#include <G4SubtractionSolid.hh>
28#include <G4Region.hh>
29#include <G4VSolid.hh>
30
31#include <G4Polycone.hh>
32#include <G4Cons.hh>
33#include <G4Colour.hh>
34#include <G4LogicalVolume.hh>
35#include <G4PVPlacement.hh>
36#include <G4Transform3D.hh>
37#include <G4VisAttributes.hh>
38#include <G4RotationMatrix.hh>
39#include <G4UserLimits.hh>
40#include <iostream>
41
42using namespace std;
43
44namespace Belle2 {
49
50 using namespace geometry;
51
52 namespace CDC {
53
57
59
60 //-----------------------------------------------------------------
61 // Implementation
62 //-----------------------------------------------------------------
63
65 {
66 // Set job control params. before sensitivedetector and geometry construction
69
70 m_logicalCDC = 0;
71 m_physicalCDC = 0;
72 m_VisAttributes.clear();
73 m_VisAttributes.push_back(new G4VisAttributes(false)); // for "invisible"
74 m_userLimits.clear();
75 }
76
77
79 {
80 delete m_sensitive;
82 for (BkgSensitiveDetector* sensitiveDetector : m_BkgSensitiveRib4)
83 delete sensitiveDetector;
84 for (G4VisAttributes* visAttr : m_VisAttributes) delete visAttr;
85 m_VisAttributes.clear();
86 for (G4UserLimits* userLimits : m_userLimits) delete userLimits;
87 m_userLimits.clear();
88 }
89
90 void GeoCDCCreator::createGeometry(const CDCGeometry& geo, G4LogicalVolume& topVolume, geometry::GeometryTypes)
91 {
92
93 m_sensitive = new CDCSensitiveDetector("CDCSensitiveDetector", (2 * 24)* CLHEP::eV, 10 * CLHEP::MeV);
94
95 const G4double realTemperture = (273.15 + 23.) * CLHEP::kelvin;
96 G4Material* medHelium = geometry::Materials::get("CDCHeGas");
97 G4Material* medEthane = geometry::Materials::get("CDCEthaneGas");
98 G4Material* medAluminum = geometry::Materials::get("Al");
99 G4Material* medTungsten = geometry::Materials::get("W");
100 G4Material* medCFRP = geometry::Materials::get("CFRP");
101 G4Material* medNEMA_G10_Plate = geometry::Materials::get("NEMA_G10_Plate");
102 G4Material* medGlue = geometry::Materials::get("CDCGlue");
103 G4Material* medAir = geometry::Materials::get("Air");
104
105 G4double h2odensity = 1.000 * CLHEP::g / CLHEP::cm3;
106 G4double a = 1.01 * CLHEP::g / CLHEP::mole;
107 G4Element* elH = new G4Element("Hydrogen", "H", 1., a);
108 a = 16.00 * CLHEP::g / CLHEP::mole;
109 G4Element* elO = new G4Element("Oxygen", "O", 8., a);
110 G4Material* medH2O = new G4Material("Water", h2odensity, 2);
111 medH2O->AddElement(elH, 2);
112 medH2O->AddElement(elO, 1);
113 G4Material* medCopper = geometry::Materials::get("Cu");
114 G4Material* medHV = geometry::Materials::get("CDCHVCable");
115 //G4Material* medFiber = geometry::Materials::get("CDCOpticalFiber");
116 //G4Material* medCAT7 = geometry::Materials::get("CDCCAT7");
117 //G4Material* medTRG = geometry::Materials::get("CDCOpticalFiberTRG");
118
119 // Total cross section
120 const double rmax_innerWall = geo.getFiducialRmin();
121 const double rmin_outerWall = geo.getFiducialRmax();
122 const double diameter_senseWire = geo.getSenseDiameter();
123 const double diameter_fieldWire = geo.getFieldDiameter();
124 const double num_senseWire = static_cast<double>(geo.getNSenseWires());
125 const double num_fieldWire = static_cast<double>(geo.getNFieldWires());
126 double totalCS = M_PI * (rmin_outerWall * rmin_outerWall - rmax_innerWall * rmax_innerWall);
127
128 // Sense wire cross section
129 double senseCS = M_PI * (diameter_senseWire / 2) * (diameter_senseWire / 2) * num_senseWire;
130
131 // Field wire cross section
132 double fieldCS = M_PI * (diameter_fieldWire / 2) * (diameter_fieldWire / 2) * num_fieldWire;
133
134 // Density
135 const double denHelium = medHelium->GetDensity() / 2.0;
136 const double denEthane = medEthane->GetDensity() / 2.0;
137 const double denAluminum = medAluminum->GetDensity() * (fieldCS / totalCS);
138 const double denTungsten = medTungsten->GetDensity() * (senseCS / totalCS);
139 const double density = denHelium + denEthane + denAluminum + denTungsten;
140 G4Material* cdcMed = new G4Material("CDCGasWire", density, 4, kStateGas, realTemperture);
141 cdcMed->AddMaterial(medHelium, denHelium / density);
142 cdcMed->AddMaterial(medEthane, denEthane / density);
143 cdcMed->AddMaterial(medTungsten, denTungsten / density);
144 cdcMed->AddMaterial(medAluminum, denAluminum / density);
145
146 G4Material* cdcMedGas = cdcMed;
147
150 // std::cout << gcp.getMaterialDefinitionMode() << std::endl;
151
152 // if (cdcgp.getMaterialDefinitionMode() == 2) {
153 if (gcp.getMaterialDefinitionMode() == 2) {
154 const double density2 = denHelium + denEthane;
155 cdcMedGas = new G4Material("CDCRealGas", density2, 2, kStateGas, realTemperture);
156 cdcMedGas->AddMaterial(medHelium, denHelium / density2);
157 cdcMedGas->AddMaterial(medEthane, denEthane / density2);
158 }
159
160 if (gcp.getPrintMaterialTable()) {
161 G4cout << *(G4Material::GetMaterialTable());
162 }
163
164 const auto& mother = geo.getMotherVolume();
165 const auto& motherRmin = mother.getRmin();
166 const auto& motherRmax = mother.getRmax();
167 const auto& motherZ = mother.getZ();
168 G4Polycone* solid_cdc =
169 new G4Polycone("solidCDC", 0 * CLHEP::deg, 360.* CLHEP::deg,
170 mother.getNNodes(), motherZ.data(),
171 motherRmin.data(), motherRmax.data());
172 m_logicalCDC = new G4LogicalVolume(solid_cdc, medAir, "logicalCDC", 0, 0, 0);
173 m_physicalCDC = new G4PVPlacement(0, G4ThreeVector(geo.getGlobalOffsetX() * CLHEP::cm,
174 geo.getGlobalOffsetY() * CLHEP::cm,
175 geo.getGlobalOffsetZ() * CLHEP::cm), m_logicalCDC,
176 "physicalCDC", &topVolume, false, 0);
177
178 // Set up region for production cuts
179 G4Region* aRegion = new G4Region("CDCEnvelope");
180 m_logicalCDC->SetRegion(aRegion);
181 aRegion->AddRootLogicalVolume(m_logicalCDC);
182
183 m_VisAttributes.push_back(new G4VisAttributes(true, G4Colour(0., 1., 0.)));
184 for (const auto& wall : geo.getOuterWalls()) {
185 const int iOuterWall = wall.getId();
186 const string wallName = wall.getName();
187 const double wallRmin = wall.getRmin();
188 const double wallRmax = wall.getRmax();
189 const double wallZfwd = wall.getZfwd();
190 const double wallZbwd = wall.getZbwd();
191 const double length = (wallZfwd - wallZbwd) / 2.0;
192
193
194 G4Material* medWall;
195 if (strstr((wallName).c_str(), "MiddleWall") != nullptr) {
196 medWall = medCFRP;
197 } else {
198 medWall = medAluminum;
199 }
200 G4Tubs* outerWallTubeShape = new G4Tubs("solid" + wallName, wallRmin * CLHEP::cm,
201 wallRmax * CLHEP::cm, length * CLHEP::cm, 0 * CLHEP::deg, 360.*CLHEP::deg);
202
203 G4LogicalVolume* outerWallTube = new G4LogicalVolume(outerWallTubeShape, medWall, "solid" + wallName, 0, 0, 0);
204 outerWallTube->SetVisAttributes(m_VisAttributes.back());
205 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (length + wallZbwd)*CLHEP::cm), outerWallTube, "logical" + wallName,
206 m_logicalCDC, false, iOuterWall);
207 }
208
209
210 m_VisAttributes.push_back(new G4VisAttributes(true, G4Colour(0., 1., 0.)));
211 for (const auto& wall : geo.getInnerWalls()) {
212 const string wallName = wall.getName();
213 const double wallRmin = wall.getRmin();
214 const double wallRmax = wall.getRmax();
215 const double wallZfwd = wall.getZfwd();
216 const double wallZbwd = wall.getZbwd();
217 const double length = (wallZfwd - wallZbwd) / 2.0;
218 const int iInnerWall = wall.getId();
219
220 G4Material* medWall;
221 if (strstr(wallName.c_str(), "MiddleWall") != nullptr) {
222 medWall = medCFRP;
223 } else if (strstr(wallName.c_str(), "MiddleGlue") != nullptr) { // Glue layer 0.005 mmt
224 medWall = medGlue;
225 } else { // Al layer 0.1 mmt
226 medWall = medAluminum;
227 }
228
229 G4Tubs* innerWallTubeShape = new G4Tubs("solid" + wallName, wallRmin * CLHEP::cm,
230 wallRmax * CLHEP::cm, length * CLHEP::cm, 0 * CLHEP::deg, 360.*CLHEP::deg);
231 G4LogicalVolume* innerWallTube = new G4LogicalVolume(innerWallTubeShape, medWall, "logical" + wallName, 0, 0, 0);
232 innerWallTube->SetVisAttributes(m_VisAttributes.back());
233 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (length + wallZbwd)*CLHEP::cm), innerWallTube, "physical" + wallName,
234 m_logicalCDC, false, iInnerWall);
235
236
237 }
238
239
240
241 //
242 // Construct sensitive layers.
243 //
244 const uint nSLayer = geo.getNSenseLayers();
245 const double length_feedthrough = geo.getFeedthroughLength();
246 for (uint iSLayer = 0; iSLayer < nSLayer; ++iSLayer) {
247 // Get parameters for sensitive layer: left, middle and right.
248 double rmin_sensitive_left, rmax_sensitive_left;
249 double rmin_sensitive_middle, rmax_sensitive_middle;
250 double rmin_sensitive_right, rmax_sensitive_right;
251 double zback_sensitive_left, zfor_sensitive_left;
252 double zback_sensitive_middle, zfor_sensitive_middle;
253 double zback_sensitive_right, zfor_sensitive_right;
254
255 if (not getEndplateInformation(geo, iSLayer,
256 rmin_sensitive_left, rmax_sensitive_left, zback_sensitive_left, zfor_sensitive_left,
257 rmin_sensitive_middle, rmax_sensitive_middle, zback_sensitive_middle, zfor_sensitive_middle,
258 rmin_sensitive_right, rmax_sensitive_right, zback_sensitive_right, zfor_sensitive_right)) {
259 continue;
260 }
261
262 // Check if build left sensitive tube
263 if ((zfor_sensitive_left - zback_sensitive_left) > length_feedthrough) {
264 // std::cout <<"left doif " << iSLayer <<" "<< zfor_sensitive_left - zback_sensitive_left << std::endl;
265 //==========================================================
266 // zback_sensitive_left
267 // |
268 // \|/
269 // _____________________
270 // | |// 1 // | |
271 // | |==ft====|2 | (ft = feedthrouth)
272 // |_______|____1___|__|
273 // |_______|___________|
274 // |
275 // \|/
276 // zfor_sensitive_left
277 //==========================================================
278
279 // Build a tube with metarial cdcMed for area 1
280 G4Tubs* leftTubeShape = new G4Tubs((boost::format("solidCDCLayer_%1%_leftTube") % iSLayer).str().c_str(),
281 rmin_sensitive_left * CLHEP::cm,
282 rmax_sensitive_left * CLHEP::cm, length_feedthrough * CLHEP::cm / 2.0, 0 * CLHEP::deg, 360.*CLHEP::deg);
283 G4LogicalVolume* leftTube = new G4LogicalVolume(leftTubeShape, cdcMed,
284 (boost::format("logicalCDCLayer_%1%_leftTube") % iSLayer).str().c_str(), 0, 0, 0);
285 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (zback_sensitive_left + length_feedthrough / 2.0)*CLHEP::cm), leftTube,
286 (boost::format("physicalCDCLayer_%1%_leftTube") % iSLayer).str().c_str(), m_logicalCDC, false, iSLayer);
287 // Build left sensitive tube (area 2)
288 G4Tubs* leftSensitiveTubeShape = new G4Tubs((boost::format("solidSD_CDCLayer_%1%_left") % iSLayer).str().c_str(),
289 rmin_sensitive_left * CLHEP::cm, rmax_sensitive_left * CLHEP::cm,
290 (zfor_sensitive_left - zback_sensitive_left - length_feedthrough)*CLHEP::cm / 2.0, 0 * CLHEP::deg, 360.*CLHEP::deg);
291 G4LogicalVolume* leftSensitiveTube = new G4LogicalVolume(leftSensitiveTubeShape, cdcMed,
292 (boost::format("logicalSD_CDCLayer_%1%_left") % iSLayer).str().c_str(), 0, 0, 0);
293 leftSensitiveTube->SetSensitiveDetector(m_sensitive);
294 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (zfor_sensitive_left + zback_sensitive_left + length_feedthrough)*CLHEP::cm / 2.0),
295 leftSensitiveTube, (boost::format("physicalSD_CDCLayer_%1%_left") % iSLayer).str().c_str(), m_logicalCDC, false, iSLayer);
296 } else {
297 // std::cout <<"left doelse " << iSLayer << std::endl;
298 //==========================================================
299 // zback_sensitive_left
300 // |
301 // \|/
302 // _________________________
303 // | |//// 1 ////| 2 |
304 // | |======ft======== (ft = feedthrouth)
305 // |_______|____1______| 2 |
306 // |_______|___________|___|
307 // |
308 // \|/
309 // zfor_sensitive_left
310 //==========================================================
311
312 // Build a tube with metarial cdcMed for area 1
313 G4Tubs* leftTubeShape = new G4Tubs((boost::format("solidCDCLayer_%1%_leftTube") % iSLayer).str().c_str(),
314 rmin_sensitive_left * CLHEP::cm,
315 rmax_sensitive_left * CLHEP::cm, (zfor_sensitive_left - zback_sensitive_left)*CLHEP::cm / 2.0, 0 * CLHEP::deg, 360.*CLHEP::deg);
316 G4LogicalVolume* leftTube = new G4LogicalVolume(leftTubeShape, cdcMed,
317 (boost::format("logicalCDCLayer_%1%_leftTube") % iSLayer).str().c_str(), 0, 0, 0);
318 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (zfor_sensitive_left + zback_sensitive_left)*CLHEP::cm / 2.0), leftTube,
319 (boost::format("physicalCDCLayer_%1%_leftTube") % iSLayer).str().c_str(), m_logicalCDC, false, iSLayer);
320
321
322 // Build a tube with metarial cdcMed for area 2
323 G4Tubs* leftMidTubeShape = new G4Tubs((boost::format("solidCDCLayer_%1%_leftMidTube") % iSLayer).str().c_str(),
324 rmin_sensitive_middle * CLHEP::cm, rmax_sensitive_middle * CLHEP::cm,
325 (length_feedthrough - zfor_sensitive_left + zback_sensitive_left)*CLHEP::cm / 2.0, 0 * CLHEP::deg, 360.*CLHEP::deg);
326 G4LogicalVolume* leftMidTube = new G4LogicalVolume(leftMidTubeShape, cdcMed,
327 (boost::format("logicalCDCLayer_%1%_leftMidTube") % iSLayer).str().c_str(), 0, 0, 0);
328
329 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (length_feedthrough + zfor_sensitive_left + zback_sensitive_left)*CLHEP::cm / 2.0),
330 leftMidTube, (boost::format("physicalCDCLayer_%1%_leftMidTube") % iSLayer).str().c_str(), m_logicalCDC, false, iSLayer);
331
332 // Reset zback_sensitive_middle
333 zback_sensitive_middle = length_feedthrough + zback_sensitive_left;
334 }
335
336 // Check if build right sensitive tube
337 if ((zfor_sensitive_right - zback_sensitive_right) > length_feedthrough) {
338 // std::cout <<"right doif" << iSLayer <<" "<< zfor_sensitive_right - zback_sensitive_right << std::endl;
339 //==========================================================
340 // zfor_sensitive_right
341 // |
342 // \|/
343 // _____________________________
344 // | | 1 |///////|
345 // | 2 |====ft=====|///////| (ft = feedthrouth)
346 // |_______|____1______|_______|
347 // |_______|___________|_______|
348 // |
349 // \|/
350 // zback_sensitive_right
351 //==========================================================
352
353 // Build a tube with metarial cdcMed for area 1
354 G4Tubs* rightTubeShape = new G4Tubs((boost::format("solidCDCLayer_%1%_rightTube") % iSLayer).str().c_str(),
355 rmin_sensitive_right * CLHEP::cm, rmax_sensitive_right * CLHEP::cm, length_feedthrough * CLHEP::cm / 2.0, 0 * CLHEP::deg,
356 360.*CLHEP::deg);
357 G4LogicalVolume* rightTube = new G4LogicalVolume(rightTubeShape, cdcMed,
358 (boost::format("logicalCDCLayer_%1%_rightTube") % iSLayer).str().c_str(), 0, 0, 0);
359
360 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (zfor_sensitive_right - length_feedthrough / 2.0)*CLHEP::cm), rightTube,
361 (boost::format("physicalCDCLayer_%1%_rightTube") % iSLayer).str().c_str(), m_logicalCDC, false, iSLayer);
362
363
364 // Build right sensitive tube (area 2)
365 G4Tubs* rightSensitiveTubeShape = new G4Tubs((boost::format("solidSD_CDCLayer_%1%_right") % iSLayer).str().c_str(),
366 rmin_sensitive_right * CLHEP::cm, rmax_sensitive_right * CLHEP::cm,
367 (zfor_sensitive_right - zback_sensitive_right - length_feedthrough)*CLHEP::cm / 2.0, 0 * CLHEP::deg, 360.*CLHEP::deg);
368 G4LogicalVolume* rightSensitiveTube = new G4LogicalVolume(rightSensitiveTubeShape, cdcMed,
369 (boost::format("logicalSD_CDCLayer_%1%_right") % iSLayer).str().c_str(), 0, 0, 0);
370 rightSensitiveTube->SetSensitiveDetector(m_sensitive);
371
372 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (zfor_sensitive_right + zback_sensitive_right - length_feedthrough)*CLHEP::cm / 2.0),
373 rightSensitiveTube, (boost::format("physicalSD_CDCLayer_%1%_right") % iSLayer).str().c_str(), m_logicalCDC, false, iSLayer);
374
375 } else {
376 // std::cout <<"right doelse" << iSLayer << std::endl;
377 //==========================================================
378 // zfor_sensitive_right
379 // |
380 // \|/
381 // _____________________________
382 // | | 1 |///////|
383 // |============ft=====|///////| (ft = feedthrouth)
384 // | |____1______|_______|
385 // |_______|___________|_______|
386 // |
387 // \|/
388 // zback_sensitive_right
389 //==========================================================
390
391 // Build a tube with metarial cdcMed for area 1
392 G4Tubs* rightTubeShape = new G4Tubs((boost::format("solidCDCLayer_%1%_rightTube") % iSLayer).str().c_str(),
393 rmin_sensitive_right * CLHEP::cm, rmax_sensitive_right * CLHEP::cm, (zfor_sensitive_right - zback_sensitive_right)*CLHEP::cm / 2.0,
394 0 * CLHEP::deg, 360.*CLHEP::deg);
395 G4LogicalVolume* rightTube = new G4LogicalVolume(rightTubeShape, cdcMed,
396 (boost::format("logicalCDCLayer_%1%_rightTube") % iSLayer).str().c_str(), 0, 0, 0);
397
398 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (zfor_sensitive_right + zback_sensitive_right)*CLHEP::cm / 2.0), rightTube,
399 (boost::format("physicalCDCLayer_%1%_rightTube") % iSLayer).str().c_str(), m_logicalCDC, false, iSLayer);
400
401
402 // Build a tube with metarial cdcMed for area 2
403 G4Tubs* rightMidTubeShape = new G4Tubs((boost::format("solidCDCLayer_%1%_rightMidTube") % iSLayer).str().c_str(),
404 rmin_sensitive_middle * CLHEP::cm, rmax_sensitive_middle * CLHEP::cm,
405 (length_feedthrough - zfor_sensitive_right + zback_sensitive_right)*CLHEP::cm / 2.0, 0 * CLHEP::deg, 360.*CLHEP::deg);
406 G4LogicalVolume* rightMidTube = new G4LogicalVolume(rightMidTubeShape, cdcMed,
407 (boost::format("logicalCDCLayer_%1%_rightMidTube") % iSLayer).str().c_str(), 0, 0, 0);
408 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (zback_sensitive_right - length_feedthrough + zfor_sensitive_right)*CLHEP::cm / 2.0),
409 rightMidTube, (boost::format("physicalCDCLayer_%1%_rightMidTube") % iSLayer).str().c_str(), m_logicalCDC, false, iSLayer);
410
411 // Reset zback_sensitive_middle
412 zfor_sensitive_middle = zfor_sensitive_right - length_feedthrough;
413 }
414
415
416 // Middle sensitive tube
417 G4Tubs* middleSensitiveTubeShape = new G4Tubs((boost::format("solidSD_CDCLayer_%1%_middle") % iSLayer).str().c_str(),
418 rmin_sensitive_middle * CLHEP::cm, rmax_sensitive_middle * CLHEP::cm,
419 (zfor_sensitive_middle - zback_sensitive_middle)*CLHEP::cm / 2.0, 0 * CLHEP::deg, 360.*CLHEP::deg);
420 G4LogicalVolume* middleSensitiveTube = new G4LogicalVolume(middleSensitiveTubeShape, cdcMedGas,
421 (boost::format("logicalSD_CDCLayer_%1%_middle") % iSLayer).str().c_str(), 0, 0, 0);
422 //hard-coded temporarily
423 //need to create an object per layer ??? to be checked later
424 G4UserLimits* uLimits = new G4UserLimits(8.5 * CLHEP::cm);
425 m_userLimits.push_back(uLimits);
426 middleSensitiveTube->SetUserLimits(uLimits);
427 middleSensitiveTube->SetSensitiveDetector(m_sensitive);
428
429 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (zfor_sensitive_middle + zback_sensitive_middle)*CLHEP::cm / 2.0), middleSensitiveTube,
430 (boost::format("physicalSD_CDCLayer_%1%_middle") % iSLayer).str().c_str(), m_logicalCDC, false, iSLayer);
431
432 // if (cdcgp.getMaterialDefinitionMode() == 2) {
433 if (gcp.getMaterialDefinitionMode() == 2) {
434 G4String sName = "sWire";
435 const G4int jc = 0;
436 B2Vector3D wb0 = cdcgp.wireBackwardPosition(iSLayer, jc);
437 // G4double rsense0 = wb0.Perp();
438 B2Vector3D wf0 = cdcgp.wireForwardPosition(iSLayer, jc);
439 G4double tAtZ0 = -wb0.Z() / (wf0.Z() - wb0.Z()); //t: param. along the wire
440 B2Vector3D wAtZ0 = wb0 + tAtZ0 * (wf0 - wb0);
441 //additional chop of wire; must be larger than 126um*(1/10), where 126um is the field wire diameter; 1/10: approx. stereo angle
442 const G4double epsl = 25.e-4; // (in cm);
443 G4double reductionBwd = (zback_sensitive_middle + epsl) / wb0.Z();
444 //chop the wire at zback_sensitive_middle for avoiding overlap; this is because the wire length defined by wb0 and wf0 is larger than the length of middle sensitive tube
445 wb0 = reductionBwd * (wb0 - wAtZ0) + wAtZ0;
446 //chop wire at zfor_sensitive_middle for avoiding overlap
447 G4double reductionFwd = (zfor_sensitive_middle - epsl) / wf0.Z();
448 wf0 = reductionFwd * (wf0 - wAtZ0) + wAtZ0;
449
450 const G4double wireHalfLength = 0.5 * (wf0 - wb0).Mag() * CLHEP::cm;
451 const G4double sWireRadius = 0.5 * cdcgp.senseWireDiameter() * CLHEP::cm;
452 // const G4double sWireRadius = 15.e-4 * CLHEP::cm;
453 G4Tubs* middleSensitiveSwireShape = new G4Tubs(sName, 0., sWireRadius, wireHalfLength, 0., 360. * CLHEP::deg);
454 G4LogicalVolume* middleSensitiveSwire = new G4LogicalVolume(middleSensitiveSwireShape, medTungsten, sName);
455 // middleSensitiveSwire->SetSensitiveDetector(m_sensitive);
456 middleSensitiveSwire->SetVisAttributes(m_VisAttributes.front()); // <- to speed up visualization
457
458 G4String fName = "fWire";
459 const G4double fWireRadius = 0.5 * cdcgp.fieldWireDiameter() * CLHEP::cm;
460 G4Tubs* middleSensitiveFwireShape = new G4Tubs(fName, 0., fWireRadius, wireHalfLength, 0., 360. * CLHEP::deg);
461 G4LogicalVolume* middleSensitiveFwire = new G4LogicalVolume(middleSensitiveFwireShape, medAluminum, fName);
462 // middleSensitiveFwire->SetSensitiveDetector(m_sensitive);
463 middleSensitiveFwire->SetVisAttributes(m_VisAttributes.front()); // <- to speed up visualization
464
465 const G4double diameter = cdcgp.fieldWireDiameter();
466
467 const G4int nCells = cdcgp.nWiresInLayer(iSLayer);
468 const G4double dphi = M_PI / nCells;
469 const B2Vector3D unitZ(0., 0., 1.);
470
471 for (int ic = 0; ic < nCells; ++ic) {
472 //define sense wire
473 B2Vector3D wb = cdcgp.wireBackwardPosition(iSLayer, ic);
474 B2Vector3D wf = cdcgp.wireForwardPosition(iSLayer, ic);
475 G4double tAtZ02 = -wb.Z() / (wf.Z() - wb.Z());
476 B2Vector3D wAtZ02 = wb + tAtZ02 * (wf - wb);
477 G4double reductionBwd2 = (zback_sensitive_middle + epsl) / wb.Z();
478 wb = reductionBwd2 * (wb - wAtZ02) + wAtZ02;
479 G4double reductionFwd2 = (zfor_sensitive_middle - epsl) / wf.Z();
480 wf = reductionFwd2 * (wf - wAtZ02) + wAtZ02;
481
482 G4double thetaYZ = -asin((wf - wb).Y() / (wf - wb).Mag());
483
484 B2Vector3D fMinusBInZX((wf - wb).X(), 0., (wf - wb).Z());
485 G4double thetaZX = asin((unitZ.Cross(fMinusBInZX)).Y() / fMinusBInZX.Mag());
486 G4RotationMatrix rotM;
487 // std::cout <<"deg,rad= " << CLHEP::deg <<" "<< CLHEP::rad << std::endl;
488 rotM.rotateX(thetaYZ * CLHEP::rad);
489 rotM.rotateY(thetaZX * CLHEP::rad);
490
491 G4ThreeVector xyz(0.5 * (wb.X() + wf.X()) * CLHEP::cm,
492 0.5 * (wb.Y() + wf.Y()) * CLHEP::cm, 0.);
493
494 // std::cout <<"0 x,y= " << xyz.getX() <<" "<< xyz.getY() << std::endl;
495 //Calling G4PVPlacement with G4Transform3D is convenient because it rotates the object instead of rotating the coordinate-frame; rotM is copied so it does not have to be created on heep by new.
496 new G4PVPlacement(G4Transform3D(rotM, xyz), middleSensitiveSwire, sName, middleSensitiveTube, false, ic);
497
498 //define field wire #1 (placed at the same phi but at the outer r boundary)
499 B2Vector3D wbF = wb;
500 G4double rF = rmax_sensitive_middle - 0.5 * diameter;
501 // std::cout <<"iSLayer,rF= " << iSLayer <<" "<< rF <<" "<< std::endl;
502 G4double phi = atan2(wbF.Y(), wbF.X());
503 wbF.SetX(rF * cos(phi));
504 wbF.SetY(rF * sin(phi));
505
506 B2Vector3D wfF = wf;
507 phi = atan2(wfF.Y(), wfF.X());
508 wfF.SetX(rF * cos(phi));
509 wfF.SetY(rF * sin(phi));
510
511 thetaYZ = -asin((wfF - wbF).Y() / (wfF - wbF).Mag());
512
513 fMinusBInZX = wfF - wbF;
514 fMinusBInZX.SetY(0.);
515 thetaZX = asin((unitZ.Cross(fMinusBInZX)).Y() / fMinusBInZX.Mag());
516
517 G4RotationMatrix rotM1;
518 rotM1.rotateX(thetaYZ * CLHEP::rad);
519 rotM1.rotateY(thetaZX * CLHEP::rad);
520
521 xyz.setX(0.5 * (wbF.X() + wfF.X()) * CLHEP::cm);
522 xyz.setY(0.5 * (wbF.Y() + wfF.Y()) * CLHEP::cm);
523
524 if (iSLayer != nSLayer - 1) {
525 // std::cout <<"1 x,y= " << xyz.getX() <<" "<< xyz.getY() << std::endl;
526 new G4PVPlacement(G4Transform3D(rotM1, xyz), middleSensitiveFwire, fName, middleSensitiveTube, false, ic);
527 }
528
529 //define field wire #2 (placed at the same radius but shifted by dphi)
530 wbF = wb;
531 rF = wbF.Perp();
532 phi = atan2(wbF.Y(), wbF.X());
533 wbF.SetX(rF * cos(phi + dphi));
534 wbF.SetY(rF * sin(phi + dphi));
535
536 wfF = wf;
537 rF = wfF.Perp();
538 phi = atan2(wfF.Y(), wfF.X());
539 wfF.SetX(rF * cos(phi + dphi));
540 wfF.SetY(rF * sin(phi + dphi));
541
542 thetaYZ = -asin((wfF - wbF).Y() / (wfF - wbF).Mag());
543
544 fMinusBInZX = wfF - wbF;
545 fMinusBInZX.SetY(0.);
546 thetaZX = asin((unitZ.Cross(fMinusBInZX)).Y() / fMinusBInZX.Mag());
547
548 G4RotationMatrix rotM2;
549 rotM2.rotateX(thetaYZ * CLHEP::rad);
550 rotM2.rotateY(thetaZX * CLHEP::rad);
551
552 xyz.setX(0.5 * (wbF.X() + wfF.X()) * CLHEP::cm);
553 xyz.setY(0.5 * (wbF.Y() + wfF.Y()) * CLHEP::cm);
554
555 // std::cout <<"2 x,y= " << xyz.getX() <<" "<< xyz.getY() << std::endl;
556 new G4PVPlacement(G4Transform3D(rotM2, xyz), middleSensitiveFwire, fName, middleSensitiveTube, false, ic + nCells);
557
558 //define field wire #3 (placed at the cell corner)
559 wbF = wb;
560 rF = rmax_sensitive_middle - 0.5 * diameter;
561 phi = atan2(wbF.Y(), wbF.X());
562 wbF.SetX(rF * cos(phi + dphi));
563 wbF.SetY(rF * sin(phi + dphi));
564
565 wfF = wf;
566 phi = atan2(wfF.Y(), wfF.X());
567 wfF.SetX(rF * cos(phi + dphi));
568 wfF.SetY(rF * sin(phi + dphi));
569
570 thetaYZ = -asin((wfF - wbF).Y() / (wfF - wbF).Mag());
571
572 fMinusBInZX = wfF - wbF;
573 fMinusBInZX.SetY(0.);
574 thetaZX = asin((unitZ.Cross(fMinusBInZX)).Y() / fMinusBInZX.Mag());
575
576 G4RotationMatrix rotM3;
577 rotM3.rotateX(thetaYZ * CLHEP::rad);
578 rotM3.rotateY(thetaZX * CLHEP::rad);
579
580 xyz.setX(0.5 * (wbF.X() + wfF.X()) * CLHEP::cm);
581 xyz.setY(0.5 * (wbF.Y() + wfF.Y()) * CLHEP::cm);
582
583 if (iSLayer != nSLayer - 1) {
584 new G4PVPlacement(G4Transform3D(rotM3, xyz), middleSensitiveFwire, fName, middleSensitiveTube, false, ic + 2 * nCells);
585 }
586 } // end of wire loop
587 } // end of wire definitions
588
589 }
590 //
591 // Endplates.
592 //
593
594 m_VisAttributes.push_back(new G4VisAttributes(true, G4Colour(1., 1., 0.)));
595 for (const auto& endplate : geo.getEndPlates()) {
596 for (const auto& epLayer : endplate.getEndPlateLayers()) {
597 const int iEPLayer = epLayer.getILayer();
598 const string name = epLayer.getName();
599 const double rmin = epLayer.getRmin();
600 const double rmax = epLayer.getRmax();
601 const double zbwd = epLayer.getZbwd();
602 const double zfwd = epLayer.getZfwd();
603 const double length = (zfwd - zbwd) / 2.0;
604
605 G4Tubs* tube = new G4Tubs("solidCDCEndplate" + name, rmin * CLHEP::cm,
606 rmax * CLHEP::cm, length * CLHEP::cm, 0 * CLHEP::deg, 360.*CLHEP::deg);
607 G4LogicalVolume* logical = new G4LogicalVolume(tube, Materials::get("G4_Al"),
608 "logicalCDCEndplate" + name, 0, 0);
609 logical->SetVisAttributes(m_VisAttributes.back());
610 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (zfwd + zbwd)*CLHEP::cm / 2.0), logical,
611 "physicalCDCEndplate" + name, m_logicalCDC, false, iEPLayer);
612
613 }
614 }
615
616
617 // Construct electronics boards
618 for (const auto& frontend : geo.getFrontends()) {
619
620 const int iEB = frontend.getId();
621 const double ebInnerR = frontend.getRmin();
622 const double ebOuterR = frontend.getRmax();
623 const double ebBZ = frontend.getZbwd();
624 const double ebFZ = frontend.getZfwd();
625
626 G4Tubs* ebTubeShape = new G4Tubs((boost::format("solidSD_ElectronicsBoard_Layer%1%") % iEB).str().c_str(), ebInnerR * CLHEP::cm,
627 ebOuterR * CLHEP::cm, (ebFZ - ebBZ)*CLHEP::cm / 2.0, 0 * CLHEP::deg, 360.*CLHEP::deg);
628
629 G4LogicalVolume* ebTube = new G4LogicalVolume(ebTubeShape, medNEMA_G10_Plate,
630 (boost::format("logicalSD_ElectronicsBoard_Layer%1%") % iEB).str().c_str(), 0, 0, 0);
631 if (!m_bkgsensitive) m_bkgsensitive = new BkgSensitiveDetector("CDC", iEB);
632 ebTube->SetSensitiveDetector(m_bkgsensitive);
633 ebTube->SetVisAttributes(m_VisAttributes.back());
634 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (ebFZ + ebBZ)*CLHEP::cm / 2.0), ebTube,
635 (boost::format("physicalSD_ElectronicsBoard_Layer%1%") % iEB).str().c_str(), m_logicalCDC, false, iEB);
636 }
637
638 //
639 // Construct neutron shield.
640 //
642
643 //
644 // construct covers.
645 //
646 createCovers(geo);
647
648 //
649 // construct covers.
650 //
651 createCover2s(geo);
652
653 //
654 // Construct ribs.
655 //
656 for (const auto& rib : geo.getRibs()) {
657
658 const int id = rib.getId();
659 const double length = rib.getLength();
660 const double width = rib.getWidth();
661 const double thick = rib.getThick();
662 const double rotx = rib.getRotX();
663 const double roty = rib.getRotY();
664 const double rotz = rib.getRotZ();
665 const double x = rib.getX();
666 const double y = rib.getY();
667 const double z = rib.getZ();
668 const int offset = rib.getOffset();
669 const int ndiv = rib.getNDiv();
670
671 const string solidName = "solidRib" + to_string(id);
672 const string logicalName = "logicalRib" + to_string(id);
673 G4Box* boxShape = new G4Box(solidName, 0.5 * length * CLHEP::cm,
674 0.5 * width * CLHEP::cm,
675 0.5 * thick * CLHEP::cm);
676
677 const double rmax = 0.5 * length;
678 const double rmin = max((rmax - thick), 0.);
679 G4Tubs* tubeShape = new G4Tubs(solidName,
680 rmin * CLHEP::cm,
681 rmax * CLHEP::cm,
682 0.5 * width * CLHEP::cm,
683 0.,
684 360. * CLHEP::deg);
685
686 //G4LogicalVolume* logicalV = new G4LogicalVolume(boxShape, medAluminum,
687 // logicalName, 0, 0, 0);
688 // ID dependent material definition, Aluminum is default
689 G4LogicalVolume* logicalV = new G4LogicalVolume(boxShape, medAluminum, logicalName, 0, 0, 0);
690 if (id > 39 && id < 78) // Cu
691 logicalV = new G4LogicalVolume(boxShape, medCopper, logicalName, 0, 0, 0);
692 if ((id > 77 && id < 94) || (id > 131 && id < 146)) // G10
693 logicalV = new G4LogicalVolume(boxShape, medNEMA_G10_Plate, logicalName, 0, 0, 0);
694 if (id > 93 && id < 110) // Cu
695 logicalV = new G4LogicalVolume(tubeShape, medCopper, logicalName, 0, 0, 0);
696 if (id > 109 && id < 126) // H2O
697 logicalV = new G4LogicalVolume(tubeShape, medH2O, logicalName, 0, 0, 0);
698 if (id > 127 && id < 132) // HV
699 logicalV = new G4LogicalVolume(boxShape, medHV, logicalName, 0, 0, 0);
700 /*if( id > 145 && id < 149 )// Fiber
701 logicalV = new G4LogicalVolume(boxShape, medFiber, logicalName, 0, 0, 0);
702 if( id > 148 && id < 158 )// Fiber
703 logicalV = new G4LogicalVolume(boxShape, medCAT7, logicalName, 0, 0, 0);
704 if( id > 157 && id < 164 )// Fiber
705 logicalV = new G4LogicalVolume(boxShape, medTRG, logicalName, 0, 0, 0);*/
706
707 logicalV->SetVisAttributes(m_VisAttributes.back());
708
709 const double phi = 360.0 / ndiv;
710
711 G4RotationMatrix rot = G4RotationMatrix();
712 double dz = thick;
713 if (id > 93 && id < 126) dz = 0;
714
715 G4ThreeVector arm(x * CLHEP::cm, y * CLHEP::cm, z * CLHEP::cm - dz * CLHEP::cm / 2.0);
716 rot.rotateX(rotx);
717 rot.rotateY(roty);
718 rot.rotateZ(rotz);
719 if (offset) {
720 rot.rotateZ(0.5 * phi * CLHEP::deg);
721 arm.rotateZ(0.5 * phi * CLHEP::deg);
722 }
723 for (int i = 0; i < ndiv; ++i) {
724 const string physicalName = "physicalRib_" + to_string(id) + " " + to_string(i);
725 new G4PVPlacement(G4Transform3D(rot, arm), logicalV,
726 physicalName.c_str(), m_logicalCDC, false, id);
727 rot.rotateZ(phi * CLHEP::deg);
728 arm.rotateZ(phi * CLHEP::deg);
729 }
730
731 }
732
733 //
734 // Construct rib2s.
735 //
736 for (const auto& rib2 : geo.getRib2s()) {
737
738 const int id = rib2.getId();
739 const double length = rib2.getLength();
740 const double width = rib2.getWidth();
741 const double thick = rib2.getThick();
742 const double width2 = rib2.getWidth2();
743 const double thick2 = rib2.getThick2();
744 const double rotx = rib2.getRotX();
745 const double roty = rib2.getRotY();
746 const double rotz = rib2.getRotZ();
747 const double x = rib2.getX();
748 const double y = rib2.getY();
749 const double z = rib2.getZ();
750 const int ndiv = rib2.getNDiv();
751
752 const string solidName = "solidRib2" + to_string(id);
753 const string logicalName = "logicalRib2" + to_string(id);
754 G4Trd* trdShape = new G4Trd(solidName,
755 0.5 * thick * CLHEP::cm,
756 0.5 * thick2 * CLHEP::cm,
757 0.5 * width * CLHEP::cm,
758 0.5 * width2 * CLHEP::cm,
759 0.5 * length * CLHEP::cm);
760
761 G4LogicalVolume* logicalV = new G4LogicalVolume(trdShape, medAluminum, logicalName, 0, 0, 0);
762
763 if (id > 0)
764 logicalV = new G4LogicalVolume(trdShape, medCopper, logicalName, 0, 0, 0);
765
766 logicalV->SetVisAttributes(m_VisAttributes.back());
767
768 const double phi = 360.0 / ndiv;
769
770 G4RotationMatrix rot = G4RotationMatrix();
771 G4ThreeVector arm(x * CLHEP::cm, y * CLHEP::cm, z * CLHEP::cm - thick * CLHEP::cm / 2.0);
772
773 rot.rotateX(rotx);
774 rot.rotateY(roty);
775 rot.rotateZ(rotz);
776 for (int i = 0; i < ndiv; ++i) {
777 const string physicalName = "physicalRib2_" + to_string(id) + " " + to_string(i);
778 new G4PVPlacement(G4Transform3D(rot, arm), logicalV,
779 physicalName.c_str(), m_logicalCDC, false, id);
780 rot.rotateZ(phi * CLHEP::deg);
781 arm.rotateZ(phi * CLHEP::deg);
782 }
783
784 }
785
786 //
787 // Construct rib3s.
788 //
789 for (const auto& rib3 : geo.getRib3s()) {
790
791 const int id = rib3.getId();
792 const double length = rib3.getLength();
793 const double width = rib3.getWidth();
794 const double thick = rib3.getThick();
795 const double r = rib3.getR();
796 const double x = rib3.getX();
797 const double y = rib3.getY();
798 const double z = rib3.getZ();
799 const double rx = rib3.getRx();
800 const double ry = rib3.getRy();
801 const double rz = rib3.getRz();
802 const int offset = rib3.getOffset();
803 const int ndiv = rib3.getNDiv();
804
805 const string logicalName = "logicalRib3" + to_string(id);
806 G4VSolid* boxShape = new G4Box("Block",
807 0.5 * length * CLHEP::cm,
808 0.5 * width * CLHEP::cm,
809 0.5 * thick * CLHEP::cm);
810 G4VSolid* tubeShape = new G4Tubs("Hole",
811 0.,
812 r * CLHEP::cm,
813 width * CLHEP::cm,
814 0. * CLHEP::deg,
815 360. * CLHEP::deg);
816
817 G4RotationMatrix rotsub = G4RotationMatrix();
818 rotsub.rotateX(90. * CLHEP::deg);
819 G4ThreeVector trnsub(rx * CLHEP::cm - x * CLHEP::cm, ry * CLHEP::cm - y * CLHEP::cm,
820 rz * CLHEP::cm - z * CLHEP::cm + 0.5 * thick * CLHEP::cm);
821 G4VSolid* coolingBlock = new G4SubtractionSolid("Block-Hole",
822 boxShape,
823 tubeShape,
824 G4Transform3D(rotsub,
825 trnsub));
826
827 G4LogicalVolume* logicalV = new G4LogicalVolume(coolingBlock, medCopper, logicalName, 0, 0, 0);
828
829 logicalV->SetVisAttributes(m_VisAttributes.back());
830
831 const double phi = 360.0 / ndiv;
832
833 G4RotationMatrix rot = G4RotationMatrix();
834 G4ThreeVector arm(x * CLHEP::cm, y * CLHEP::cm, z * CLHEP::cm - thick * CLHEP::cm / 2.0);
835
836 if (offset) {
837 rot.rotateZ(0.5 * phi * CLHEP::deg);
838 arm.rotateZ(0.5 * phi * CLHEP::deg);
839 }
840 for (int i = 0; i < ndiv; ++i) {
841 const string physicalName = "physicalRib3_" + to_string(id) + " " + to_string(i);
842 new G4PVPlacement(G4Transform3D(rot, arm), logicalV,
843 physicalName.c_str(), m_logicalCDC, false, id);
844 rot.rotateZ(phi * CLHEP::deg);
845 arm.rotateZ(phi * CLHEP::deg);
846 }
847
848 }
849
850 //
851 // Construct rib4s.
852 //
853 for (const auto& rib4 : geo.getRib4s()) {
854
855 const int id = rib4.getId();
856 const double length = rib4.getLength();
857 const double width = rib4.getWidth();
858 const double thick = rib4.getThick();
859 const double length2 = rib4.getLength2();
860 const double width2 = rib4.getWidth2();
861 const double thick2 = rib4.getThick2();
862 const double x = rib4.getX();
863 const double y = rib4.getY();
864 const double z = rib4.getZ();
865 const double x2 = rib4.getX2();
866 const double y2 = rib4.getY2();
867 const double z2 = rib4.getZ2();
868 const int offset = rib4.getOffset();
869 const int ndiv = rib4.getNDiv();
870
871 const string logicalName = "logicalRib4" + to_string(id);
872 G4VSolid* baseShape = new G4Box("Base",
873 0.5 * length * CLHEP::cm,
874 0.5 * width * CLHEP::cm,
875 0.5 * thick * CLHEP::cm);
876 G4VSolid* sqShape = new G4Box("Sq",
877 0.5 * length2 * CLHEP::cm,
878 0.5 * width2 * CLHEP::cm,
879 0.5 * thick2 * CLHEP::cm);
880
881 G4RotationMatrix rotsub = G4RotationMatrix();
882 double dzc = (z2 - thick2 / 2.) - (z - thick / 2.);
883 G4ThreeVector trnsub(x2 * CLHEP::cm - x * CLHEP::cm,
884 y2 * CLHEP::cm - y * CLHEP::cm,
885 dzc * CLHEP::cm);
886 G4VSolid* sqHoleBase = new G4SubtractionSolid("Box-Sq",
887 baseShape,
888 sqShape,
889 G4Transform3D(rotsub,
890 trnsub)
891 );
892
893 G4LogicalVolume* logicalV = new G4LogicalVolume(sqHoleBase, medCopper, logicalName, 0, 0, 0);
894 if (id < 19) {
895 logicalV = new G4LogicalVolume(sqHoleBase, medNEMA_G10_Plate, logicalName, 0, 0, 0);
896 BkgSensitiveDetector* sensitiveDetector =
897 new BkgSensitiveDetector("CDC", 2000 + id);
898 logicalV->SetSensitiveDetector(sensitiveDetector);
899 m_BkgSensitiveRib4.push_back(sensitiveDetector);
900 }
901
902 logicalV->SetVisAttributes(m_VisAttributes.back());
903
904 const double phi = 360.0 / ndiv;
905
906 G4RotationMatrix rot = G4RotationMatrix();
907 G4ThreeVector arm(x * CLHEP::cm, y * CLHEP::cm, z * CLHEP::cm - thick * CLHEP::cm / 2.0);
908
909 if (offset) {
910 rot.rotateZ(0.5 * phi * CLHEP::deg);
911 arm.rotateZ(0.5 * phi * CLHEP::deg);
912 }
913 for (int i = 0; i < ndiv; ++i) {
914 const string physicalName = "physicalRib4_" + to_string(id) + " " + to_string(i);
915 new G4PVPlacement(G4Transform3D(rot, arm), logicalV,
916 physicalName.c_str(), m_logicalCDC, false, id);
917 rot.rotateZ(phi * CLHEP::deg);
918 arm.rotateZ(phi * CLHEP::deg);
919 }
920
921 }
922 //
923 // Construct rib5s.
924 //
925 for (const auto& rib5 : geo.getRib5s()) {
926
927 const int id = rib5.getId();
928 const double dr = rib5.getDr();
929 const double dz = rib5.getDz();
930 const double width = rib5.getWidth();
931 const double thick = rib5.getThick();
932 const double rin = rib5.getRin();
933 const double x = rib5.getX();
934 const double y = rib5.getY();
935 const double z = rib5.getZ();
936 const double rotx = rib5.getRotx();
937 const double roty = rib5.getRoty();
938 const double rotz = rib5.getRotz();
939 const int offset = rib5.getOffset();
940 const int ndiv = rib5.getNDiv();
941
942 const string solidName = "solidRib5" + to_string(id);
943 const string logicalName = "logicalRib5" + to_string(id);
944
945 const double rmax = rin + thick;
946 const double rmin = rin;
947 const double dphi = 2. * atan2(dz, dr);
948 const double ddphi = thick * tan(dphi) / rin;
949 const double ddphi2 = width / 2. * width / 2. / (x + dr) / rin;
950 const double cphi = dphi - ddphi - ddphi2;
951 G4Tubs* tubeShape = new G4Tubs(solidName,
952 rmin * CLHEP::cm,
953 rmax * CLHEP::cm,
954 0.5 * width * CLHEP::cm,
955 0.,
956 cphi);
957
958 G4LogicalVolume* logicalV = new G4LogicalVolume(tubeShape, medAluminum, logicalName, 0, 0, 0);
959
960 logicalV->SetVisAttributes(m_VisAttributes.back());
961
962 const double phi = 360.0 / ndiv;
963
964 G4RotationMatrix rot = G4RotationMatrix();
965
966 //G4ThreeVector arm(x * CLHEP::cm, y * CLHEP::cm, z * CLHEP::cm - thick * CLHEP::cm / 2.0);
967 G4ThreeVector arm(x * CLHEP::cm, y * CLHEP::cm, z * CLHEP::cm - rin * CLHEP::cm - thick * CLHEP::cm);
968 rot.rotateX(rotx);
969 rot.rotateY(roty);
970 rot.rotateZ(rotz);
971 if (offset) {
972 rot.rotateZ(0.5 * phi * CLHEP::deg);
973 arm.rotateZ(0.5 * phi * CLHEP::deg);
974 }
975 for (int i = 0; i < ndiv; ++i) {
976 const string physicalName = "physicalRib5_" + to_string(id) + " " + to_string(i);
977 new G4PVPlacement(G4Transform3D(rot, arm), logicalV,
978 physicalName.c_str(), m_logicalCDC, false, id);
979 rot.rotateZ(phi * CLHEP::deg);
980 arm.rotateZ(phi * CLHEP::deg);
981 }
982
983 }
984
985 //Create B-field mapper (here tentatively)
986 createMapper(topVolume);
987 }
988
989
991 {
992
993 // G4Material* C2H4 = geometry::Materials::get("G4_POLYETHYLENE");
994 // G4Material* elB = geometry::Materials::get("G4_B");
995
996 // 5% borated polyethylene = SWX201
997 // http://www.deqtech.com/Shieldwerx/Products/swx201hd.htm
998 // G4Material* boratedpoly05 = new G4Material("BoratedPoly05", 1.06 * CLHEP::g / CLHEP::cm3, 2);
999 // boratedpoly05->AddMaterial(elB, 0.05);
1000 // boratedpoly05->AddMaterial(C2H4, 0.95);
1001 // 30% borated polyethylene = SWX210
1002 // G4Material* boratedpoly30 = new G4Material("BoratedPoly30", 1.19 * CLHEP::g / CLHEP::cm3, 2);
1003 // boratedpoly30->AddMaterial(elB, 0.30);
1004 // boratedpoly30->AddMaterial(C2H4, 0.70);
1005
1006 // G4Material* shieldMat = C2H4;
1007
1008 G4Material* SWX238 = geometry::Materials::get("CDC-SWX-238");
1009 G4Material* shieldMat = SWX238;
1010
1011 const int nShields = content.getNumberNodes("Shields/Shield");
1012
1013 for (int iShield = 0; iShield < nShields; ++iShield) {
1014 GearDir shieldContent(content);
1015 shieldContent.append((boost::format("/Shields/Shield[%1%]/") % (iShield + 1)).str());
1016 const string sShieldID = shieldContent.getString("@id");
1017 const int shieldID = atoi(sShieldID.c_str());
1018 // const string shieldName = shieldContent.getString("Name");
1019 const double shieldInnerR1 = shieldContent.getLength("InnerR1");
1020 const double shieldInnerR2 = shieldContent.getLength("InnerR2");
1021 const double shieldOuterR1 = shieldContent.getLength("OuterR1");
1022 const double shieldOuterR2 = shieldContent.getLength("OuterR2");
1023 const double shieldThick = shieldContent.getLength("Thickness");
1024 const double shieldPosZ = shieldContent.getLength("PosZ");
1025 const int enableShield = shieldContent.getInt("Enable");
1026
1027 G4Cons* shieldConsShape = new G4Cons((boost::format("solidShield%1%") % shieldID).str().c_str(),
1028 shieldInnerR1 * CLHEP::cm, shieldOuterR1 * CLHEP::cm,
1029 shieldInnerR2 * CLHEP::cm, shieldOuterR2 * CLHEP::cm,
1030 shieldThick * CLHEP::cm / 2.0,
1031 0.*CLHEP::deg, 360.*CLHEP::deg);
1032
1033 G4LogicalVolume* shieldCons = new G4LogicalVolume(shieldConsShape, shieldMat,
1034 (boost::format("logicalShield%1%") % shieldID).str().c_str(),
1035 0, 0, 0);
1036 shieldCons->SetVisAttributes(m_VisAttributes.back());
1037
1038 if (enableShield) {
1039 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (shieldPosZ - shieldThick / 2.0) * CLHEP::cm), shieldCons,
1040 (boost::format("physicalShield%1%") % shieldID).str().c_str(), m_logicalCDC, false, 0);
1041 G4cout << "_____________" << G4endl << shieldCons->GetName() << " (Shield) : mass = " << shieldCons->GetMass() / CLHEP::kg <<
1042 " | materials : " << shieldCons->GetMaterial() << G4endl << "_____________" << G4endl;
1043 }
1044
1045 }
1046
1047 }
1048
1049
1051 {
1052
1053 // G4Material* C2H4 = geometry::Materials::get("G4_POLYETHYLENE");
1054 // G4Material* shieldMat = C2H4;
1055
1056 G4Material* SWX238 = geometry::Materials::get("CDC-SWX-238");
1057 G4Material* shieldMat = SWX238;
1058
1059 for (const auto& shield : geom.getNeutronShields()) {
1060 const int shieldID = shield.getId();
1061 const double shieldInnerR1 = shield.getRmin1();
1062 const double shieldInnerR2 = shield.getRmin2();
1063 const double shieldOuterR1 = shield.getRmax1();
1064 const double shieldOuterR2 = shield.getRmax2();
1065 const double shieldThick = shield.getThick();
1066 const double shieldPosZ = shield.getZ();
1067 const int enableShield = shield.getEna();
1068
1069 G4Cons* shieldConsShape = new G4Cons("solidShield" + to_string(shieldID),
1070 shieldInnerR1 * CLHEP::cm, shieldOuterR1 * CLHEP::cm,
1071 shieldInnerR2 * CLHEP::cm, shieldOuterR2 * CLHEP::cm,
1072 shieldThick * CLHEP::cm / 2.0,
1073 0.*CLHEP::deg, 360.*CLHEP::deg);
1074
1075 G4LogicalVolume* shieldCons = new G4LogicalVolume(shieldConsShape, shieldMat, "logicalShield" + to_string(shieldID),
1076 0, 0, 0);
1077 shieldCons->SetVisAttributes(m_VisAttributes.back());
1078
1079 if (enableShield) {
1080 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (shieldPosZ - shieldThick / 2.0) * CLHEP::cm), shieldCons,
1081 "physicalShield" + to_string(shieldID), m_logicalCDC, false, 0);
1082 G4cout << "_____________" << G4endl << shieldCons->GetName() << " (Shield) : mass = " << shieldCons->GetMass() / CLHEP::kg <<
1083 " | materials : " << shieldCons->GetMaterial() << G4endl << "_____________" << G4endl;
1084 }
1085
1086 }
1087
1088 }
1089
1091 {
1092 string Aluminum = content.getString("Aluminum");
1093 G4Material* medAluminum = geometry::Materials::get(Aluminum);
1094 G4Material* medNEMA_G10_Plate = geometry::Materials::get("NEMA_G10_Plate");
1095 G4double density = 1.000 * CLHEP::g / CLHEP::cm3;
1096 G4double a = 1.01 * CLHEP::g / CLHEP::mole;
1097 G4Element* elH = new G4Element("Hydrogen", "H", 1., a);
1098 a = 16.00 * CLHEP::g / CLHEP::mole;
1099 G4Element* elO = new G4Element("Oxygen", "O", 8., a);
1100 G4Material* medH2O = new G4Material("Water", density, 2);
1101 medH2O->AddElement(elH, 2);
1102 medH2O->AddElement(elO, 1);
1103 G4Material* medCopper = geometry::Materials::get("Cu");
1104 G4Material* medLV = geometry::Materials::get("CDCLVCable");
1105 G4Material* medFiber = geometry::Materials::get("CDCOpticalFiber");
1106 G4Material* medCAT7 = geometry::Materials::get("CDCCAT7");
1107 G4Material* medTRG = geometry::Materials::get("CDCOpticalFiberTRG");
1108 G4Material* medHV = geometry::Materials::get("CDCHVCable");
1109
1110 m_VisAttributes.push_back(new G4VisAttributes(true, G4Colour(0., 1., 0.)));
1111 const int nCover = content.getNumberNodes("Covers/Cover");
1112 for (int iCover = 0; iCover < nCover; ++iCover) {
1113 GearDir coverContent(content);
1114 coverContent.append((boost::format("/Covers/Cover[%1%]/") % (iCover + 1)).str());
1115 const string scoverID = coverContent.getString("@id");
1116 const int coverID = atoi(scoverID.c_str());
1117 const string coverName = coverContent.getString("Name");
1118 const double coverInnerR1 = coverContent.getLength("InnerR1");
1119 const double coverInnerR2 = coverContent.getLength("InnerR2");
1120 const double coverOuterR1 = coverContent.getLength("OuterR1");
1121 const double coverOuterR2 = coverContent.getLength("OuterR2");
1122 const double coverThick = coverContent.getLength("Thickness");
1123 const double coverPosZ = coverContent.getLength("PosZ");
1124
1125 const double rmin1 = coverInnerR1;
1126 const double rmax1 = coverOuterR1;
1127 const double rmin2 = coverInnerR2;
1128 const double rmax2 = coverOuterR2;
1129
1130 /*
1131 if (coverID == 7 || coverID == 10) {
1132 createCone(rmin1, rmax1, rmin2, rmax2, coverThick, coverPosZ, coverID, medAluminum, coverName);
1133 } else {
1134 createTube(rmin1, rmax1, coverThick, coverPosZ, coverID, medAluminum, coverName);
1135
1136 }*/
1137 // ID dependent material definition
1138 if (coverID < 23) {
1139 if (coverID == 7 || coverID == 10) {// cones
1140 createCone(rmin1, rmax1, rmin2, rmax2, coverThick, coverPosZ, coverID, medAluminum, coverName);
1141 } else {// covers
1142 createTube(rmin1, rmax1, coverThick, coverPosZ, coverID, medAluminum, coverName);
1143 }
1144 }
1145 if (coverID > 22 && coverID < 29)// cooling plate
1146 createTube(rmin1, rmax1, coverThick, coverPosZ, coverID, medCopper, coverName);
1147 if (coverID > 28 && coverID < 35)// cooling Pipe
1148 createTorus(rmin1, rmax1, coverThick, coverPosZ, coverID, medCopper, coverName);
1149 if (coverID > 34 && coverID < 41)// cooling water
1150 createTorus(rmin1, rmax1, coverThick, coverPosZ, coverID, medH2O, coverName);
1151 if (coverID == 45 || coverID == 46)
1152 createTube(rmin1, rmax1, coverThick, coverPosZ, coverID, medLV, coverName);
1153 if (coverID == 47 || coverID == 48)
1154 createTube(rmin1, rmax1, coverThick, coverPosZ, coverID, medFiber, coverName);
1155 if (coverID == 49 || coverID == 50)
1156 createTube(rmin1, rmax1, coverThick, coverPosZ, coverID, medCAT7, coverName);
1157 if (coverID == 51 || coverID == 52)
1158 createTube(rmin1, rmax1, coverThick, coverPosZ, coverID, medTRG, coverName);
1159 if (coverID == 53)
1160 createTube(rmin1, rmax1, coverThick, coverPosZ, coverID, medHV, coverName);
1161 }
1162
1163 const int nCover2 = content.getNumberNodes("Covers/Cover2");
1164 for (int iCover2 = 0; iCover2 < nCover2; ++iCover2) {
1165 GearDir cover2Content(content);
1166 cover2Content.append((boost::format("/Cover2s/Cover2[%1%]/") % (iCover2 + 1)).str());
1167 const string scover2ID = cover2Content.getString("@id");
1168 const int cover2ID = atoi(scover2ID.c_str());
1169 const string cover2Name = cover2Content.getString("Name");
1170 const double cover2InnerR = cover2Content.getLength("InnerR");
1171 const double cover2OuterR = cover2Content.getLength("OuterR");
1172 const double cover2StartPhi = cover2Content.getLength("StartPhi");
1173 const double cover2DeltaPhi = cover2Content.getLength("DeltaPhi");
1174 const double cover2Thick = cover2Content.getLength("Thickness");
1175 const double cover2PosZ = cover2Content.getLength("PosZ");
1176
1177 if (cover2ID < 11)
1178 createTube2(cover2InnerR, cover2OuterR, cover2StartPhi, cover2DeltaPhi, cover2Thick, cover2PosZ, cover2ID, medHV, cover2Name);
1179 if (cover2ID > 10 && cover2ID < 14)
1180 createTube2(cover2InnerR, cover2OuterR, cover2StartPhi, cover2DeltaPhi, cover2Thick, cover2PosZ, cover2ID, medFiber, cover2Name);
1181 if (cover2ID > 13 && cover2ID < 23)
1182 createTube2(cover2InnerR, cover2OuterR, cover2StartPhi, cover2DeltaPhi, cover2Thick, cover2PosZ, cover2ID, medCAT7, cover2Name);
1183 if (cover2ID > 22 && cover2ID < 29)
1184 createTube2(cover2InnerR, cover2OuterR, cover2StartPhi, cover2DeltaPhi, cover2Thick, cover2PosZ, cover2ID, medTRG, cover2Name);
1185 }
1186
1187 const int nRibs = content.getNumberNodes("Covers/Rib");
1188 for (int iRib = 0; iRib < nRibs; ++iRib) {
1189 GearDir ribContent(content);
1190 ribContent.append((boost::format("/Covers/Rib[%1%]/") % (iRib + 1)).str());
1191 const string sribID = ribContent.getString("@id");
1192 const int ribID = atoi(sribID.c_str());
1193 // const string ribName = ribContent.getString("Name");
1194 const double length = ribContent.getLength("Length");
1195 const double width = ribContent.getLength("Width");
1196 const double thick = ribContent.getLength("Thickness");
1197 const double rotX = ribContent.getLength("RotX");
1198 const double rotY = ribContent.getLength("RotY");
1199 const double rotZ = ribContent.getLength("RotZ");
1200 const double cX = ribContent.getLength("PosX");
1201 const double cY = ribContent.getLength("PosY");
1202 const double cZ = ribContent.getLength("PosZ");
1203 const int offset = atoi((ribContent.getString("Offset")).c_str());
1204 const int number = atoi((ribContent.getString("NDiv")).c_str());
1205
1206 const string solidName = "solidRib" + to_string(ribID);
1207 const string logicalName = "logicalRib" + to_string(ribID);
1208 G4Box* boxShape = new G4Box(solidName, 0.5 * length * CLHEP::cm,
1209 0.5 * width * CLHEP::cm,
1210 0.5 * thick * CLHEP::cm);
1211 const double rmax = 0.5 * length;
1212 const double rmin = max((rmax - thick), 0.);
1213 G4Tubs* tubeShape = new G4Tubs(solidName,
1214 rmin * CLHEP::cm,
1215 rmax * CLHEP::cm,
1216 0.5 * width * CLHEP::cm,
1217 0.,
1218 360. * CLHEP::deg);
1219
1220 //G4LogicalVolume* logicalV = new G4LogicalVolume(boxShape, medAluminum,
1221 // logicalName, 0, 0, 0);
1222 // ID dependent material definition Aluminum is default
1223 G4LogicalVolume* logicalV = new G4LogicalVolume(boxShape, medAluminum, logicalName, 0, 0, 0);
1224 if (ribID > 39 && ribID < 78) // Cu box
1225 logicalV = new G4LogicalVolume(boxShape, medCopper, logicalName, 0, 0, 0);
1226 if ((ribID > 77 && ribID < 94) || (ribID > 131 && ribID < 146)) // G10 box
1227 logicalV = new G4LogicalVolume(boxShape, medNEMA_G10_Plate, logicalName, 0, 0, 0);
1228 if (ribID > 93 && ribID < 110) // Cu tube
1229 logicalV = new G4LogicalVolume(tubeShape, medCopper, logicalName, 0, 0, 0);
1230 if (ribID > 109 && ribID < 126) // H2O tube (rmin = 0)
1231 logicalV = new G4LogicalVolume(tubeShape, medH2O, logicalName, 0, 0, 0);
1232 [[clang::suppress]]
1233 if (ribID > 127 && ribID < 132) // HV bundle
1234 logicalV = new G4LogicalVolume(boxShape, medHV, logicalName, 0, 0, 0);
1235 /*if( ribID > 145 && ribID < 149 )// Fiber box
1236 logicalV = new G4LogicalVolume(boxShape, medFiber, logicalName, 0, 0, 0);
1237 if( ribID > 148 && ribID < 158 )// Fiber box
1238 logicalV = new G4LogicalVolume(boxShape, medCAT7, logicalName, 0, 0, 0);
1239 if( ribID > 157 && ribID < 164 )// Fiber box
1240 logicalV = new G4LogicalVolume(boxShape, medTRG, logicalName, 0, 0, 0);*/
1241
1242 logicalV->SetVisAttributes(m_VisAttributes.back());
1243
1244 const double phi = 360.0 / number;
1245
1246 G4RotationMatrix rot = G4RotationMatrix();
1247
1248 double dz = thick;
1249 if (ribID > 93 && ribID < 126) dz = 0;
1250 G4ThreeVector arm(cX * CLHEP::cm, cY * CLHEP::cm, cZ * CLHEP::cm - dz * CLHEP::cm / 2.0);
1251
1252 rot.rotateX(rotX);
1253 rot.rotateY(rotY);
1254 rot.rotateZ(rotZ);
1255 if (offset) {
1256 rot.rotateZ(0.5 * phi * CLHEP::deg);
1257 arm.rotateZ(0.5 * phi * CLHEP::deg);
1258 }
1259 for (int i = 0; i < number; ++i) {
1260 const string physicalName = "physicalRib_" + to_string(ribID) + " " + to_string(i);
1261 new G4PVPlacement(G4Transform3D(rot, arm), logicalV,
1262 physicalName.c_str(), m_logicalCDC, false, ribID);
1263 rot.rotateZ(phi * CLHEP::deg);
1264 arm.rotateZ(phi * CLHEP::deg);
1265 }
1266
1267 }// rib
1268
1269 const int nRib2s = content.getNumberNodes("Covers/Rib2");
1270 for (int iRib2 = 0; iRib2 < nRib2s; ++iRib2) {
1271 GearDir rib2Content(content);
1272 rib2Content.append((boost::format("/Covers/Rib2[%1%]/") % (iRib2 + 1)).str());
1273 const string srib2ID = rib2Content.getString("@id");
1274 const int rib2ID = atoi(srib2ID.c_str());
1275 // const string rib2Name = rib2Content.getString("Name");
1276 const double length = rib2Content.getLength("Length");
1277 const double width = rib2Content.getLength("Width");
1278 const double thick = rib2Content.getLength("Thickness");
1279 const double width2 = rib2Content.getLength("Width2");
1280 const double thick2 = rib2Content.getLength("Thickness2");
1281 const double rotX = rib2Content.getLength("RotX");
1282 const double rotY = rib2Content.getLength("RotY");
1283 const double rotZ = rib2Content.getLength("RotZ");
1284 const double cX = rib2Content.getLength("PosX");
1285 const double cY = rib2Content.getLength("PosY");
1286 const double cZ = rib2Content.getLength("PosZ");
1287 const int number = atoi((rib2Content.getString("NDiv")).c_str());
1288
1289 const string solidName = "solidRib2" + to_string(rib2ID);
1290 const string logicalName = "logicalRib2" + to_string(rib2ID);
1291 G4Trd* trdShape = new G4Trd(solidName,
1292 0.5 * thick * CLHEP::cm,
1293 0.5 * thick2 * CLHEP::cm,
1294 0.5 * width * CLHEP::cm,
1295 0.5 * width2 * CLHEP::cm,
1296 0.5 * length * CLHEP::cm);
1297
1298 G4LogicalVolume* logicalV = new G4LogicalVolume(trdShape, medAluminum, logicalName, 0, 0, 0);
1299 if (rib2ID > 0)
1300 logicalV = new G4LogicalVolume(trdShape, medCopper, logicalName, 0, 0, 0);
1301
1302 [[clang::suppress]]
1303 logicalV->SetVisAttributes(m_VisAttributes.back());
1304
1305 const double phi = 360.0 / number;
1306
1307 G4RotationMatrix rot = G4RotationMatrix();
1308 G4ThreeVector arm(cX * CLHEP::cm, cY * CLHEP::cm, cZ * CLHEP::cm - thick * CLHEP::cm / 2.0);
1309
1310 rot.rotateX(rotX);
1311 rot.rotateY(rotY);
1312 rot.rotateZ(rotZ);
1313 for (int i = 0; i < number; ++i) {
1314 const string physicalName = "physicalRib2_" + to_string(rib2ID) + " " + to_string(i);
1315 new G4PVPlacement(G4Transform3D(rot, arm), logicalV,
1316 physicalName.c_str(), m_logicalCDC, false, rib2ID);
1317 rot.rotateZ(phi * CLHEP::deg);
1318 arm.rotateZ(phi * CLHEP::deg);
1319 }
1320
1321 }// rib2
1322
1323 const int nRib3s = content.getNumberNodes("Covers/Rib3");
1324 for (int iRib3 = 0; iRib3 < nRib3s; ++iRib3) {
1325 GearDir rib3Content(content);
1326 rib3Content.append((boost::format("/Covers/Rib3[%1%]/") % (iRib3 + 1)).str());
1327 const string srib3ID = rib3Content.getString("@id");
1328 const int rib3ID = atoi(srib3ID.c_str());
1329 // const string rib3Name = rib3Content.getString("Name");
1330 const double length = rib3Content.getLength("Length");
1331 const double width = rib3Content.getLength("Width");
1332 const double thick = rib3Content.getLength("Thickness");
1333 const double r = rib3Content.getLength("HoleR");
1334 const double cX = rib3Content.getLength("PosX");
1335 const double cY = rib3Content.getLength("PosY");
1336 const double cZ = rib3Content.getLength("PosZ");
1337 const double hX = rib3Content.getLength("HoleX");
1338 const double hY = rib3Content.getLength("HoleY");
1339 const double hZ = rib3Content.getLength("HoleZ");
1340 const int offset = atoi((rib3Content.getString("Offset")).c_str());
1341 const int number = atoi((rib3Content.getString("NDiv")).c_str());
1342
1343 const string logicalName = "logicalRib3" + to_string(rib3ID);
1344 G4VSolid* boxShape = new G4Box("Block",
1345 0.5 * length * CLHEP::cm,
1346 0.5 * width * CLHEP::cm,
1347 0.5 * thick * CLHEP::cm);
1348 G4VSolid* tubeShape = new G4Tubs("Hole",
1349 0.,
1350 r * CLHEP::cm,
1351 length * CLHEP::cm,
1352 0.,
1353 360. * CLHEP::deg);
1354 G4RotationMatrix rotsub = G4RotationMatrix();
1355 G4ThreeVector trnsub(cX * CLHEP::cm - hX * CLHEP::cm, cY * CLHEP::cm - hY * CLHEP::cm,
1356 cZ * CLHEP::cm - hZ * CLHEP::cm + 0.5 * thick * CLHEP::cm);
1357 G4VSolid* coolingBlock = new G4SubtractionSolid("Block-Hole",
1358 boxShape,
1359 tubeShape,
1360 G4Transform3D(rotsub,
1361 trnsub));
1362
1363 G4LogicalVolume* logicalV = new G4LogicalVolume(coolingBlock, medCopper, logicalName, 0, 0, 0);
1364
1365 logicalV->SetVisAttributes(m_VisAttributes.back());
1366
1367 const double phi = 360.0 / number;
1368
1369 G4RotationMatrix rot = G4RotationMatrix();
1370 G4ThreeVector arm(cX * CLHEP::cm, cY * CLHEP::cm, cZ * CLHEP::cm - thick * CLHEP::cm / 2.0);
1371
1372 if (offset) {
1373 rot.rotateZ(0.5 * phi * CLHEP::deg);
1374 arm.rotateZ(0.5 * phi * CLHEP::deg);
1375 }
1376 for (int i = 0; i < number; ++i) {
1377 const string physicalName = "physicalRib3_" + to_string(rib3ID) + " " + to_string(i);
1378 new G4PVPlacement(G4Transform3D(rot, arm), logicalV,
1379 physicalName.c_str(), m_logicalCDC, false, rib3ID);
1380 rot.rotateZ(phi * CLHEP::deg);
1381 arm.rotateZ(phi * CLHEP::deg);
1382 }
1383
1384 }// rib3
1385
1386 const int nRib4s = content.getNumberNodes("Covers/Rib4");
1387 for (int iRib4 = 0; iRib4 < nRib4s; ++iRib4) {
1388 GearDir rib4Content(content);
1389 rib4Content.append((boost::format("/Covers/Rib4[%1%]/") % (iRib4 + 1)).str());
1390 const string srib4ID = rib4Content.getString("@id");
1391 const int rib4ID = atoi(srib4ID.c_str());
1392 // const string rib4Name = rib4Content.getString("Name");
1393 const double length = rib4Content.getLength("Length");
1394 const double width = rib4Content.getLength("Width");
1395 const double thick = rib4Content.getLength("Thickness");
1396 const double length2 = rib4Content.getLength("Length2");
1397 const double width2 = rib4Content.getLength("Width2");
1398 const double thick2 = rib4Content.getLength("Thickness2");
1399 const double cX = rib4Content.getLength("PosX");
1400 const double cY = rib4Content.getLength("PosY");
1401 const double cZ = rib4Content.getLength("PosZ");
1402 const double hX = rib4Content.getLength("HoleX");
1403 const double hY = rib4Content.getLength("HoleY");
1404 const double hZ = rib4Content.getLength("HoleZ");
1405 const int offset = atoi((rib4Content.getString("Offset")).c_str());
1406 const int number = atoi((rib4Content.getString("NDiv")).c_str());
1407
1408 const string logicalName = "logicalRib4" + to_string(rib4ID);
1409 G4VSolid* baseShape = new G4Box("Base",
1410 0.5 * length * CLHEP::cm,
1411 0.5 * width * CLHEP::cm,
1412 0.5 * thick * CLHEP::cm);
1413 G4VSolid* sqShape = new G4Box("Sq",
1414 0.5 * length2 * CLHEP::cm,
1415 0.5 * width2 * CLHEP::cm,
1416 0.5 * thick2 * CLHEP::cm);
1417 G4RotationMatrix rotsub = G4RotationMatrix();
1418 double dzc = (hZ - thick2 / 2.) - (cZ - thick / 2.);
1419 G4ThreeVector trnsub(hX * CLHEP::cm - cX * CLHEP::cm,
1420 hY * CLHEP::cm - cY * CLHEP::cm,
1421 dzc * CLHEP::cm);
1422 G4VSolid* sqHoleBase = new G4SubtractionSolid("Base-Sq",
1423 baseShape,
1424 sqShape,
1425 G4Transform3D(rotsub,
1426 trnsub)
1427 );
1428
1429 G4LogicalVolume* logicalV = new G4LogicalVolume(sqHoleBase, medCopper, logicalName, 0, 0, 0);
1430 if (rib4ID < 19)
1431 logicalV = new G4LogicalVolume(sqHoleBase, medNEMA_G10_Plate, logicalName, 0, 0, 0);
1432
1433 logicalV->SetVisAttributes(m_VisAttributes.back());
1434
1435 const double phi = 360.0 / number;
1436
1437 G4RotationMatrix rot = G4RotationMatrix();
1438 G4ThreeVector arm(cX * CLHEP::cm, cY * CLHEP::cm, cZ * CLHEP::cm - thick * CLHEP::cm / 2.0);
1439
1440 if (offset) {
1441 rot.rotateZ(0.5 * phi * CLHEP::deg);
1442 arm.rotateZ(0.5 * phi * CLHEP::deg);
1443 }
1444 for (int i = 0; i < number; ++i) {
1445 const string physicalName = "physicalRib4_" + to_string(rib4ID) + " " + to_string(i);
1446 new G4PVPlacement(G4Transform3D(rot, arm), logicalV,
1447 physicalName.c_str(), m_logicalCDC, false, rib4ID);
1448 rot.rotateZ(phi * CLHEP::deg);
1449 arm.rotateZ(phi * CLHEP::deg);
1450 }
1451
1452 }// rib4
1453
1454 const int nRib5s = content.getNumberNodes("Covers/Rib5");
1455 for (int iRib5 = 0; iRib5 < nRib5s; ++iRib5) {
1456 GearDir rib5Content(content);
1457 rib5Content.append((boost::format("/Covers/Rib5[%1%]/") % (iRib5 + 1)).str());
1458 const string srib5ID = rib5Content.getString("@id");
1459 const int rib5ID = atoi(srib5ID.c_str());
1460 // const string rib5Name = rib5Content.getString("Name");
1461 const double dr = rib5Content.getLength("DeltaR");
1462 const double dz = rib5Content.getLength("DeltaZ");
1463 const double width = rib5Content.getLength("Width");
1464 const double thick = rib5Content.getLength("Thickness");
1465 const double rin = rib5Content.getLength("Rin");
1466 const double rotX = rib5Content.getLength("RotX");
1467 const double rotY = rib5Content.getLength("RotY");
1468 const double rotZ = rib5Content.getLength("RotZ");
1469 const double cX = rib5Content.getLength("PosX");
1470 const double cY = rib5Content.getLength("PosY");
1471 const double cZ = rib5Content.getLength("PosZ");
1472 const int offset = atoi((rib5Content.getString("Offset")).c_str());
1473 const int number = atoi((rib5Content.getString("NDiv")).c_str());
1474
1475 const string solidName = "solidRib5" + to_string(rib5ID);
1476 const string logicalName = "logicalRib5" + to_string(rib5ID);
1477 const double rmax = rin + thick;
1478 const double rmin = rin;
1479 const double dphi = 2. * atan2(dz, dr);
1480 const double ddphi = thick * tan(dphi) / rin;
1481 const double ddphi2 = width / 2. * width / 2. / (cX + dr) / rin;
1482 const double cphi = dphi - ddphi - ddphi2;
1483 G4Tubs* tubeShape = new G4Tubs(solidName,
1484 rmin * CLHEP::cm,
1485 rmax * CLHEP::cm,
1486 0.5 * width * CLHEP::cm,
1487 0.,
1488 cphi);
1489
1490 G4LogicalVolume* logicalV = new G4LogicalVolume(tubeShape, medAluminum, logicalName, 0, 0, 0);
1491
1492 logicalV->SetVisAttributes(m_VisAttributes.back());
1493
1494 const double phi = 360.0 / number;
1495
1496 G4RotationMatrix rot = G4RotationMatrix();
1497
1498 //G4ThreeVector arm(cX * CLHEP::cm, cY * CLHEP::cm, cZ * CLHEP::cm - thick * CLHEP::cm / 2.0);
1499 G4ThreeVector arm(cX * CLHEP::cm, cY * CLHEP::cm, cZ * CLHEP::cm - rin * CLHEP::cm - thick * CLHEP::cm);
1500
1501 rot.rotateX(rotX);
1502 rot.rotateY(rotY);
1503 rot.rotateZ(rotZ);
1504 if (offset) {
1505 rot.rotateZ(0.5 * phi * CLHEP::deg);
1506 arm.rotateZ(0.5 * phi * CLHEP::deg);
1507 }
1508 for (int i = 0; i < number; ++i) {
1509 const string physicalName = "physicalRib5_" + to_string(rib5ID) + " " + to_string(i);
1510 new G4PVPlacement(G4Transform3D(rot, arm), logicalV,
1511 physicalName.c_str(), m_logicalCDC, false, rib5ID);
1512 rot.rotateZ(phi * CLHEP::deg);
1513 arm.rotateZ(phi * CLHEP::deg);
1514 }
1515 }//rib5
1516
1517 }
1518
1519
1521 {
1522 G4Material* medAl = geometry::Materials::get("Al");
1523 G4double density = 1.000 * CLHEP::g / CLHEP::cm3;
1524 G4double a = 1.01 * CLHEP::g / CLHEP::mole;
1525 G4Element* elH = new G4Element("Hydrogen", "H", 1., a);
1526 a = 16.00 * CLHEP::g / CLHEP::mole;
1527 G4Element* elO = new G4Element("Oxygen", "O", 8., a);
1528 G4Material* medH2O = new G4Material("water", density, 2);
1529 medH2O->AddElement(elH, 2);
1530 medH2O->AddElement(elO, 1);
1531 G4Material* medCu = geometry::Materials::get("Cu");
1532 G4Material* medLV = geometry::Materials::get("CDCLVCable");
1533 G4Material* medFiber = geometry::Materials::get("CDCOpticalFiber");
1534 G4Material* medCAT7 = geometry::Materials::get("CDCCAT7");
1535 G4Material* medTRG = geometry::Materials::get("CDCOpticalFiberTRG");
1536 G4Material* medHV = geometry::Materials::get("CDCHVCable");
1537
1538 m_VisAttributes.push_back(new G4VisAttributes(true, G4Colour(0., 1., 0.)));
1539 for (const auto& cover : geom.getCovers()) {
1540 const int coverID = cover.getId();
1541 const string coverName = "cover" + to_string(coverID);
1542 const double rmin1 = cover.getRmin1();
1543 const double rmin2 = cover.getRmin2();
1544 const double rmax1 = cover.getRmax1();
1545 const double rmax2 = cover.getRmax2();
1546 const double thick = cover.getThick();
1547 const double posZ = cover.getZ();
1548
1549 /*if (coverID == 7 || coverID == 10) {
1550 createCone(rmin1, rmax1, rmin2, rmax2, thick, posZ, coverID, medAl, coverName);
1551 } else {
1552 createTube(rmin1, rmax1, thick, posZ, coverID, medAl, coverName);
1553 }*/
1554 // ID dependent material definition
1555 if (coverID < 23) {
1556 if (coverID == 7 || coverID == 10) {
1557 createCone(rmin1, rmax1, rmin2, rmax2, thick, posZ, coverID, medAl, coverName);
1558 } else {
1559 createTube(rmin1, rmax1, thick, posZ, coverID, medAl, coverName);
1560 }
1561 }
1562 if (coverID > 22 && coverID < 29)
1563 createTube(rmin1, rmax1, thick, posZ, coverID, medCu, coverName);
1564 if (coverID > 28 && coverID < 35)
1565 createTorus(rmin1, rmax1, thick, posZ, coverID, medCu, coverName);
1566 if (coverID > 34 && coverID < 41)
1567 createTorus(rmin1, rmax1, thick, posZ, coverID, medH2O, coverName);
1568 if (coverID == 45 || coverID == 46)
1569 createTube(rmin1, rmax1, thick, posZ, coverID, medLV, coverName);
1570 if (coverID == 47 || coverID == 48)
1571 createTube(rmin1, rmax1, thick, posZ, coverID, medFiber, coverName);
1572 if (coverID == 49 || coverID == 50)
1573 createTube(rmin1, rmax1, thick, posZ, coverID, medCAT7, coverName);
1574 if (coverID == 51 || coverID == 52)
1575 createTube(rmin1, rmax1, thick, posZ, coverID, medTRG, coverName);
1576 if (coverID == 53)
1577 createTube(rmin1, rmax1, thick, posZ, coverID, medHV, coverName);
1578 }
1579 }
1580
1582 {
1583 G4Material* medHV = geometry::Materials::get("CDCHVCable");
1584 G4Material* medFiber = geometry::Materials::get("CDCOpticalFiber");
1585 G4Material* medCAT7 = geometry::Materials::get("CDCCAT7");
1586 G4Material* medTRG = geometry::Materials::get("CDCOpticalFiberTRG");
1587
1588 m_VisAttributes.push_back(new G4VisAttributes(true, G4Colour(0., 1., 0.)));
1589 for (const auto& cover2 : geom.getCover2s()) {
1590 const int cover2ID = cover2.getId();
1591 const string cover2Name = "cover2" + to_string(cover2ID);
1592 const double rmin = cover2.getRmin();
1593 const double rmax = cover2.getRmax();
1594 const double phis = cover2.getPhis();
1595 const double dphi = cover2.getDphi();
1596 const double thick = cover2.getThick();
1597 const double posZ = cover2.getZ();
1598
1599 if (cover2ID < 11)
1600 createTube2(rmin, rmax, phis, dphi, thick, posZ, cover2ID, medHV, cover2Name);
1601 if (cover2ID > 10 && cover2ID < 14)
1602 createTube2(rmin, rmax, phis, dphi, thick, posZ, cover2ID, medFiber, cover2Name);
1603 if (cover2ID > 13 && cover2ID < 23)
1604 createTube2(rmin, rmax, phis, dphi, thick, posZ, cover2ID, medCAT7, cover2Name);
1605 if (cover2ID > 22 && cover2ID < 29)
1606 createTube2(rmin, rmax, phis, dphi, thick, posZ, cover2ID, medTRG, cover2Name);
1607 }
1608 }
1609
1610 void GeoCDCCreator::createCone(const double rmin1, const double rmax1,
1611 const double rmin2, const double rmax2,
1612 const double thick, const double posZ,
1613 const int id, G4Material* med,
1614 const string& name)
1615 {
1616 const string solidName = "solid" + name;
1617 const string logicalName = "logical" + name;
1618 const string physicalName = "physical" + name;
1619 G4Cons* coverConeShape = new G4Cons(solidName.c_str(), rmin1 * CLHEP::cm, rmax1 * CLHEP::cm,
1620 rmin2 * CLHEP::cm, rmax2 * CLHEP::cm, thick * CLHEP::cm / 2.0, 0.*CLHEP::deg, 360.*CLHEP::deg);
1621 G4LogicalVolume* coverCone = new G4LogicalVolume(coverConeShape, med,
1622 logicalName.c_str(), 0, 0, 0);
1623 coverCone->SetVisAttributes(m_VisAttributes.back());
1624 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, posZ * CLHEP::cm - thick * CLHEP::cm / 2.0), coverCone,
1625 physicalName.c_str(), m_logicalCDC, false, id);
1626
1627 }
1628
1629 void GeoCDCCreator::createTube(const double rmin, const double rmax,
1630 const double thick, const double posZ,
1631 const int id, G4Material* med,
1632 const string& name)
1633 {
1634 const string solidName = "solid" + name;
1635 const string logicalName = "logical" + name;
1636 const string physicalName = "physical" + name;
1637 G4Tubs* solidV = new G4Tubs(solidName.c_str(),
1638 rmin * CLHEP::cm,
1639 rmax * CLHEP::cm,
1640 thick * CLHEP::cm / 2.0,
1641 0.*CLHEP::deg,
1642 360.*CLHEP::deg);
1643 G4LogicalVolume* logicalV = new G4LogicalVolume(solidV, med,
1644 logicalName.c_str(), 0, 0, 0);
1645 logicalV->SetVisAttributes(m_VisAttributes.back());
1646 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, posZ * CLHEP::cm - thick * CLHEP::cm / 2.0), logicalV,
1647 physicalName.c_str(), m_logicalCDC, false, id);
1648
1649 }
1650
1651 void GeoCDCCreator::createBox(const double length, const double height,
1652 const double thick, const double x,
1653 const double y, const double z,
1654 const int id, G4Material* med,
1655 const string& name)
1656 {
1657 const string solidName = (boost::format("solid%1%%2%") % name % id).str();
1658 const string logicalName = (boost::format("logical%1%%2%") % name % id).str();
1659 const string physicalName = (boost::format("physical%1%%2%") % name % id).str();
1660 G4Box* boxShape = new G4Box(solidName.c_str(), 0.5 * length * CLHEP::cm,
1661 0.5 * height * CLHEP::cm,
1662 0.5 * thick * CLHEP::cm);
1663 G4LogicalVolume* logicalV = new G4LogicalVolume(boxShape, med,
1664 logicalName.c_str(), 0, 0, 0);
1665 logicalV->SetVisAttributes(m_VisAttributes.back());
1666 new G4PVPlacement(0, G4ThreeVector(x * CLHEP::cm, y * CLHEP::cm, z * CLHEP::cm - thick * CLHEP::cm / 2.0), logicalV,
1667 physicalName.c_str(), m_logicalCDC, false, id);
1668
1669 }
1670
1671 void GeoCDCCreator::createTorus(const double rmin1, const double rmax1,
1672 const double thick, const double posZ,
1673 const int id, G4Material* med,
1674 const string& name)
1675 {
1676 const string solidName = "solid" + name;
1677 const string logicalName = "logical" + name;
1678 const string physicalName = "physical" + name;
1679 const double rtor = (rmax1 + rmin1) / 2.;
1680 const double rmax = rmax1 - rtor;
1681 const double rmin = max((rmax - thick), 0.);
1682
1683 G4Torus* solidV = new G4Torus(solidName.c_str(),
1684 rmin * CLHEP::cm,
1685 rmax * CLHEP::cm,
1686 rtor * CLHEP::cm,
1687 0.*CLHEP::deg,
1688 360.*CLHEP::deg);
1689 G4LogicalVolume* logicalV = new G4LogicalVolume(solidV, med,
1690 logicalName.c_str(), 0, 0, 0);
1691 logicalV->SetVisAttributes(m_VisAttributes.back());
1692 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, posZ * CLHEP::cm), logicalV,
1693 physicalName.c_str(), m_logicalCDC, false, id);
1694
1695 }
1696
1697 void GeoCDCCreator::createTube2(const double rmin, const double rmax,
1698 const double phis, const double phie,
1699 const double thick, const double posZ,
1700 const int id, G4Material* med,
1701 const string& name)
1702 {
1703 const string solidName = "solid" + name;
1704 const string logicalName = "logical" + name;
1705 const string physicalName = "physical" + name;
1706 G4Tubs* solidV = new G4Tubs(solidName.c_str(),
1707 rmin * CLHEP::cm,
1708 rmax * CLHEP::cm,
1709 thick * CLHEP::cm / 2.0,
1710 phis,
1711 phie);
1712 G4LogicalVolume* logicalV = new G4LogicalVolume(solidV, med,
1713 logicalName.c_str(), 0, 0, 0);
1714 logicalV->SetVisAttributes(m_VisAttributes.back());
1715 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, posZ * CLHEP::cm - thick * CLHEP::cm / 2.0), logicalV,
1716 physicalName.c_str(), m_logicalCDC, false, id);
1717
1718 }
1719
1720 void GeoCDCCreator::createMapper(G4LogicalVolume& topVolume)
1721 {
1723 if (!gcp.getMapperGeometry()) return;
1724
1725 const double xc = 0.5 * (-0.0002769 + 0.0370499) * CLHEP::cm;
1726 const double yc = 0.5 * (-0.0615404 + -0.108948) * CLHEP::cm;
1727 const double zc = 0.5 * (-35.3 + 48.5) * CLHEP::cm;
1728 //3 plates
1729 // const double plateWidth = 13.756 * CLHEP::cm;
1730 // const double plateThick = 1.203 * CLHEP::cm;
1731 // const double plateLength = 83.706 * CLHEP::cm;
1732 const double plateWidth = 13.8 * CLHEP::cm;
1733 const double plateThick = 1.2 * CLHEP::cm;
1734 const double plateLength = 83.8 * CLHEP::cm;
1735 const double phi = gcp.getMapperPhiAngle() * CLHEP::deg; //phi-angle in lab.
1736 // std::cout << "phi= " << phi << std::endl;
1737 // const double endRingRmin = 4.1135 * CLHEP::cm;
1738 // const double endRingRmax = 15.353 * CLHEP::cm;
1739 // const double endRingThick = 2.057 * CLHEP::cm;
1740 const double endPlateRmin = 4.0 * CLHEP::cm;
1741 const double endPlateRmax = 15.5 * CLHEP::cm;
1742 const double bwdEndPlateThick = 1.7 * CLHEP::cm;
1743 const double fwdEndPlateThick = 2.0 * CLHEP::cm;
1744
1745 G4Material* medAluminum = geometry::Materials::get("Al");
1746
1747 string name = "Plate";
1748 int pID = 0;
1749 G4Box* plateShape = new G4Box("solid" + name, .5 * plateWidth, .5 * plateThick, .5 * plateLength);
1750 G4LogicalVolume* logical0 = new G4LogicalVolume(plateShape, medAluminum, "logical" + name, 0, 0, 0);
1751 logical0->SetVisAttributes(m_VisAttributes.back());
1752 // const double x = .5 * plateWidth;
1753 const double x = xc + 0.5 * plateWidth;
1754 // const double y = endRingRmin;
1755 const double y = yc + endPlateRmin + 0.1 * CLHEP::cm;
1756 // double z = 2.871 * CLHEP::cm;
1757 G4ThreeVector xyz(x, y, zc);
1758 G4RotationMatrix rotM3 = G4RotationMatrix();
1759 xyz.rotateZ(phi);
1760 rotM3.rotateZ(phi);
1761 new G4PVPlacement(G4Transform3D(rotM3, xyz), logical0, "physical" + name, &topVolume, false, pID);
1762
1763 const double alf = 120. * CLHEP::deg;
1764 xyz.rotateZ(alf);
1765 rotM3.rotateZ(alf);
1766 new G4PVPlacement(G4Transform3D(rotM3, xyz), logical0, "physical" + name, &topVolume, false, pID + 1);
1767
1768 xyz.rotateZ(alf);
1769 rotM3.rotateZ(alf);
1770 new G4PVPlacement(G4Transform3D(rotM3, xyz), logical0, "physical" + name, &topVolume, false, pID + 2);
1771
1772 //Define 2 end-plates
1773 //bwd
1774 name = "BwdEndPlate";
1775 G4Tubs* BwdEndPlateShape = new G4Tubs("solid" + name, endPlateRmin, endPlateRmax, 0.5 * bwdEndPlateThick, 0., 360.*CLHEP::deg);
1776 G4LogicalVolume* logical1 = new G4LogicalVolume(BwdEndPlateShape, medAluminum, "logical" + name, 0, 0, 0);
1777 logical1->SetVisAttributes(m_VisAttributes.back());
1778 // z = -40.0105 * CLHEP::cm;
1779 double z = -35.3 * CLHEP::cm - 0.5 * bwdEndPlateThick;
1780 pID = 0;
1781 new G4PVPlacement(0, G4ThreeVector(xc, yc, z), logical1, "physical" + name, &topVolume, false, pID);
1782
1783 //fwd
1784 // z = 45.7525 * CLHEP::cm;
1785 // new G4PVPlacement(0, G4ThreeVector(0., 0., z), logical1, "physical" + name, &topVolume, false, pID + 1);
1786 name = "FwdEndPlate";
1787 G4Tubs* FwdEndPlateShape = new G4Tubs("solid" + name, endPlateRmin, endPlateRmax, 0.5 * fwdEndPlateThick, 0., 360.*CLHEP::deg);
1788 G4LogicalVolume* logical2 = new G4LogicalVolume(FwdEndPlateShape, medAluminum, "logical" + name, 0, 0, 0);
1789 logical2->SetVisAttributes(m_VisAttributes.back());
1790 z = 48.5 * CLHEP::cm + 0.5 * fwdEndPlateThick;
1791 new G4PVPlacement(0, G4ThreeVector(xc, yc, z), logical2, "physical" + name, &topVolume, false, pID);
1792 }
1793
1794 bool GeoCDCCreator::getEndplateInformation(const CDCGeometry& geo, const uint iSLayer,
1795 double& rMinLeft, double& rMaxLeft, double& zBackLeft, double& zForLeft,
1796 double& rMinMiddle, double& rMaxMiddle, double& zBackMiddle, double& zForMiddle,
1797 double& rMinRight, double& rMaxRight, double& zBackRight, double& zForRight) const
1798 {
1799 const auto& endplate = geo.getEndPlate(iSLayer);
1800 const int nEPLayer = endplate.getNEndPlateLayers();
1801
1802 if (iSLayer == 0) {
1803 const auto& epLayerBwd = endplate.getEndPlateLayer(0);
1804 const auto& epLayerFwd = endplate.getEndPlateLayer(nEPLayer / 2);
1805 const auto& senseLayer = geo.getSenseLayer(iSLayer);
1806 const auto& fieldLayer = geo.getFieldLayer(iSLayer);
1807
1808 rMinLeft = epLayerBwd.getRmax();
1809 rMaxLeft = fieldLayer.getR();
1810 zBackLeft = senseLayer.getZbwd();
1811 zForLeft = epLayerBwd.getZfwd();
1812
1813 rMinMiddle = (geo.getInnerWall(0)).getRmax();
1814 rMaxMiddle = fieldLayer.getR();
1815 zBackMiddle = epLayerBwd.getZfwd();
1816 zForMiddle = epLayerFwd.getZbwd();
1817
1818 rMinRight = epLayerFwd.getRmax();
1819 rMaxRight = fieldLayer.getR();
1820 zBackRight = epLayerFwd.getZbwd();
1821 zForRight = senseLayer.getZfwd();
1822 } else if (iSLayer >= 1 && iSLayer <= 14) {
1823 const auto& epLayerBwd = endplate.getEndPlateLayer(1);
1824 const auto& epLayerFwd = endplate.getEndPlateLayer((nEPLayer / 2) + 1);
1825 const auto& senseLayer = geo.getSenseLayer(iSLayer);
1826 const auto& fieldLayerIn = geo.getFieldLayer(iSLayer - 1);
1827 const auto& fieldLayerOut = geo.getFieldLayer(iSLayer);
1828
1829 rMinLeft = epLayerBwd.getRmax();
1830 rMaxLeft = fieldLayerOut.getR();
1831 zBackLeft = senseLayer.getZbwd();
1832 zForLeft = epLayerBwd.getZfwd();
1833
1834 rMinMiddle = fieldLayerIn.getR();
1835 rMaxMiddle = fieldLayerOut.getR();
1836 zBackMiddle = epLayerBwd.getZfwd();
1837 zForMiddle = epLayerFwd.getZbwd();
1838
1839 rMinRight = epLayerFwd.getRmax();
1840 rMaxRight = fieldLayerOut.getR();
1841 zBackRight = epLayerFwd.getZbwd();
1842 zForRight = senseLayer.getZfwd();
1843 } else if (iSLayer >= 15 && iSLayer <= 18) {
1844 const auto& epLayerBwd = endplate.getEndPlateLayer(1);
1845 const auto& epLayerFwd = endplate.getEndPlateLayer(nEPLayer / 2);
1846 const auto& senseLayer = geo.getSenseLayer(iSLayer);
1847 const auto& fieldLayerIn = geo.getFieldLayer(iSLayer - 1);
1848 const auto& fieldLayerOut = geo.getFieldLayer(iSLayer);
1849
1850 rMinLeft = epLayerBwd.getRmax();
1851 rMaxLeft = fieldLayerOut.getR();
1852 zBackLeft = senseLayer.getZbwd();
1853 zForLeft = epLayerBwd.getZfwd();
1854
1855 rMinMiddle = fieldLayerIn.getR();
1856 rMaxMiddle = fieldLayerOut.getR();
1857 zBackMiddle = epLayerBwd.getZfwd();
1858 zForMiddle = epLayerFwd.getZbwd();
1859
1860 rMinRight = epLayerFwd.getRmax();
1861 rMaxRight = fieldLayerOut.getR();
1862 zBackRight = epLayerFwd.getZbwd();
1863 zForRight = senseLayer.getZfwd();
1864 } else if (iSLayer >= 19 && iSLayer < 55) {
1865 const auto& epLayerBwd = endplate.getEndPlateLayer(0);
1866 const auto& epLayerFwd = endplate.getEndPlateLayer(nEPLayer / 2);
1867 const auto& senseLayer = geo.getSenseLayer(iSLayer);
1868 const auto& fieldLayerIn = geo.getFieldLayer(iSLayer - 1);
1869 const auto& fieldLayerOut = geo.getFieldLayer(iSLayer);
1870
1871 rMinLeft = epLayerBwd.getRmax();
1872 rMaxLeft = fieldLayerOut.getR();
1873 zBackLeft = senseLayer.getZbwd();
1874 zForLeft = epLayerBwd.getZfwd();
1875
1876 rMinMiddle = fieldLayerIn.getR();
1877 rMaxMiddle = fieldLayerOut.getR();
1878 zBackMiddle = epLayerBwd.getZfwd();
1879 zForMiddle = epLayerFwd.getZbwd();
1880
1881 rMinRight = epLayerFwd.getRmax();
1882 rMaxRight = fieldLayerOut.getR();
1883 zBackRight = epLayerFwd.getZbwd();
1884 zForRight = senseLayer.getZfwd();
1885
1886 } else if (iSLayer == 55) {
1887
1888 const auto& epLayerBwdIn = endplate.getEndPlateLayer(0);
1889 const auto& epLayerBwdOut = endplate.getEndPlateLayer((nEPLayer / 2) - 1);
1890 const auto& epLayerFwdIn = endplate.getEndPlateLayer(nEPLayer / 2);
1891 const auto& epLayerFwdOut = endplate.getEndPlateLayer(nEPLayer - 1);
1892 const auto& senseLayer = geo.getSenseLayer(iSLayer);
1893
1894 int iSLayerMinus1 = iSLayer - 1; //avoid cpp-check warning
1895 const auto& fieldLayerIn = geo.getFieldLayer(iSLayerMinus1); //avoid cpp-check warning
1896 rMinLeft = epLayerBwdIn.getRmax();
1897 rMaxLeft = epLayerBwdOut.getRmax();
1898 zBackLeft = senseLayer.getZbwd();
1899 zForLeft = epLayerBwdIn.getZfwd();
1900
1901 rMinMiddle = fieldLayerIn.getR();
1902 rMaxMiddle = (geo.getOuterWall(0)).getRmin();
1903 zBackMiddle = epLayerBwdIn.getZfwd();
1904 zForMiddle = epLayerFwdIn.getZbwd();
1905
1906 rMinRight = epLayerFwdIn.getRmax();
1907 rMaxRight = epLayerFwdOut.getRmax();
1908 zBackRight = epLayerFwdIn.getZbwd();
1909 zForRight = senseLayer.getZfwd();
1910
1911 } else {
1912 B2ERROR("Undefined sensitive layer : " << iSLayer);
1913 return false;
1914 }
1915 return true;
1916 }
1917 }
1919}
DataType Z() const
access variable Z (= .at(2) without boundary check)
Definition B2Vector3.h:439
void SetX(DataType x)
set X/1st-coordinate
Definition B2Vector3.h:463
B2Vector3< DataType > Cross(const B2Vector3< DataType > &p) const
Cross product.
Definition B2Vector3.h:298
DataType X() const
access variable X (= .at(0) without boundary check)
Definition B2Vector3.h:435
DataType Y() const
access variable Y (= .at(1) without boundary check)
Definition B2Vector3.h:437
DataType Mag() const
The magnitude (rho in spherical coordinate system).
Definition B2Vector3.h:161
void SetY(DataType y)
set Y/2nd-coordinate
Definition B2Vector3.h:465
DataType Perp() const
The transverse component (R in cylindrical coordinate system).
Definition B2Vector3.h:202
The Class for BeamBackground Sensitive Detector.
int getNEndPlateLayers() const
Get the number of endplate layers.
double getR() const
Get Radius.
double getZbwd() const
Get bwd z-position.
const std::vector< double > & getRmin() const
Get the list of the Rmin coordinates.
The Class for CDC geometry.
Definition CDCGeometry.h:27
double getGlobalOffsetY() const
Get the global y offset of CDC wrt Belle2 coord.
FieldLayer getFieldLayer(int i) const
Get the i-th field layer.
OuterWall getOuterWall(int i) const
Get the i-th outer wall.
double getFiducialRmin() const
Get the fiducial Rmin of CDC sensitive volume.
const std::vector< Rib4 > & getRib4s() const
Get the list of rib4s.
const std::vector< Rib5 > & getRib5s() const
Get the list of rib5s.
const std::vector< Frontend > & getFrontends() const
Get the list of frontend layers.
double getGlobalOffsetX() const
Get the global x offset of CDC wrt Belle2 coord.
double getFiducialRmax() const
Get the fiducial Rmax of CDC sensitive volume.
int getNFieldWires() const
Get the number of field wires.
const std::vector< Rib3 > & getRib3s() const
Get the list of rib3s.
int getNSenseWires() const
Get the number of sense wires.
double getSenseDiameter() const
Get the diameter of sense wire.
InnerWall getInnerWall(int i) const
Get the i-th inner wall.
double getFieldDiameter() const
Get the diameter of field wire.
EndPlate getEndPlate(int i) const
Get the i-th endplate.
const std::vector< Rib2 > & getRib2s() const
Get the list of rib2s.
const std::vector< Rib > & getRibs() const
Get the list of ribs.
int getNSenseLayers() const
Get the number of sense layers.
double getFeedthroughLength() const
Get the length of feedthrough.
const std::vector< OuterWall > & getOuterWalls() const
Get the list of outer walls.
double getGlobalOffsetZ() const
Get the global z offset of CDC wrt Belle2 coord.
const std::vector< InnerWall > & getInnerWalls() const
Get the list of inner walls.
const std::vector< EndPlate > & getEndPlates() const
Get the list of endplates.
const MotherVolume & getMotherVolume() const
Get the mother volume geometry of CDC.
SenseLayer getSenseLayer(int i) const
Get i-th sense layer.
The Class for CDC Geometry Control Parameters.
bool getPrintMaterialTable() const
Get printMaterialTable flag.
double getMaterialDefinitionMode() const
Get material definition mode.
bool getMapperGeometry()
Get mapper geometry flag.
double getMapperPhiAngle()
Get mapper phi-angle.
static CDCGeoControlPar & getInstance()
Static method to get a reference to the CDCGeoControlPar instance.
The Class for CDC Geometry Parameters.
double fieldWireDiameter() const
Returns diameter of the field wire.
const B2Vector3D wireForwardPosition(uint layerId, int cellId, EWirePosition set=c_Base) const
Returns the forward position of the input sense wire.
double senseWireDiameter() const
Returns diameter of the sense wire.
const B2Vector3D wireBackwardPosition(uint layerId, int cellId, EWirePosition set=c_Base) const
Returns the backward position of the input sense wire.
unsigned nWiresInLayer(int layerId) const
Returns wire numbers in a layer.
static CDCGeometryPar & Instance(const CDCGeometry *=nullptr)
Static method to get a reference to the CDCGeometryPar instance.
The Class for CDC Sensitive Detector.
static CDCSimControlPar & getInstance()
Static method to get a reference to the CDCSimControlPar instance.
void createBox(const double length, const double height, const double thick, const double x, const double y, const double z, const int id, G4Material *med, const std::string &name)
Create G4Box.
std::vector< G4VisAttributes * > m_VisAttributes
Vector of pointers to G4VisAttributes.
std::vector< G4UserLimits * > m_userLimits
Vector of pointers to G4UserLimits.
BkgSensitiveDetector * m_bkgsensitive
Sensitive detector for background studies.
virtual bool getEndplateInformation(const CDCGeometry &geo, const uint iSLayer, double &rMinLeft, double &rMaxLeft, double &zBackLeft, double &zForLeft, double &rMinMiddle, double &rMaxMiddle, double &zBackMiddle, double &zForMiddle, double &rMinRight, double &rMaxRight, double &zBackRight, double &zForRight) const
Get endplate information.
void createGeometry(const CDCGeometry &parameters, G4LogicalVolume &topVolume, geometry::GeometryTypes type)
Create G4 geometry of CDC.
void createTube2(const double rmin, const double rmax, const double phis, const double phie, const double thick, const double posZ, const int id, G4Material *med, const std::string &name)
Create G4Tube2.
~GeoCDCCreator() override
The destructor of the GeoCDCCreator class.
void createTube(const double rmin, const double rmax, const double thick, const double posZ, const int id, G4Material *med, const std::string &name)
Create G4Tube.
GeoCDCCreator()
Constructor of the GeoCDCCreator class.
void createNeutronShields(const GearDir &content)
Create neutron shield from gearbox.
G4VPhysicalVolume * m_physicalCDC
CDC G4 physical volume.
void createTorus(const double rmin1, const double rmax1, const double thick, const double posZ, const int id, G4Material *med, const std::string &name)
Create G4Torus.
std::vector< BkgSensitiveDetector * > m_BkgSensitiveRib4
Sensitive detectors for background studies (rib4).
void createCone(const double rmin1, const double rmax1, const double rmin2, const double rmax2, const double thick, const double posz, const int id, G4Material *med, const std::string &name)
Create G4Cone.
void createCover2s(const GearDir &content)
Create CDC cover2s from gear box.
void createMapper(G4LogicalVolume &topVolume)
Create the B-field mapper geometry (tentative function)
G4LogicalVolume * m_logicalCDC
CDC G4 logical volume.
void createCovers(const GearDir &content)
Create CDC covers from gear box.
CDCSensitiveDetector * m_sensitive
Sensitive detector.
GearDir is the basic class used for accessing the parameter store.
Definition GearDir.h:31
void append(const std::string &path)
Append something to the current path, modifying the GearDir in place.
Definition GearDir.h:52
virtual std::string getString(const std::string &path="") const noexcept(false) override
Get the parameter path as a string.
Definition GearDir.h:69
double getLength(const std::string &path="") const noexcept(false)
Get the parameter path as a double converted to the standard length unit.
Definition Interface.h:259
int getInt(const std::string &path="") const noexcept(false)
Get the parameter path as a int.
Definition Interface.cc:60
static G4Material * get(const std::string &name)
Find given material.
Definition Materials.h:63
B2Vector3< double > B2Vector3D
typedef for common usage with double
Definition B2Vector3.h:522
double tan(double a)
tan for double
Definition beamHelpers.h:31
geometry::CreatorFactory< GeoCDCCreator > GeoCDCFactory("CDCCreator")
Register the GeoCreator.
Common code concerning the geometry representation of the detector.
Definition CreatorBase.h:25
GeometryTypes
Flag indicating the type of geometry to be used.
Abstract base class for different kinds of events.
STL namespace.
Very simple class to provide an easy way to register creators with the CreatorManager.