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