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