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