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;
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);
117
118
119
120
121
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
131 double senseCS = M_PI * (diameter_senseWire / 2) * (diameter_senseWire / 2) * num_senseWire;
132
133
134 double fieldCS = M_PI * (diameter_fieldWire / 2) * (diameter_fieldWire / 2) * num_fieldWire;
135
136
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
152
153
154
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,
178 "physicalCDC", &topVolume, false, 0);
179
180
181 G4Region* aRegion = new G4Region("CDCEnvelope");
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);
207 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (length + wallZbwd)*CLHEP::cm), outerWallTube, "logical" + wallName,
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) {
226 medWall = medGlue;
227 } else {
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);
235 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (length + wallZbwd)*CLHEP::cm), innerWallTube, "physical" + wallName,
237
238
239 }
240
241
242
243
244
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
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
351 int iSLayerMinus1 = iSLayer - 1;
352 const auto& fieldLayerIn = geo.getFieldLayer(iSLayerMinus1);
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
375 if ((zfor_sensitive_left - zback_sensitive_left) > length_feedthrough) {
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
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
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
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
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
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
443 zback_sensitive_middle = length_feedthrough + zback_sensitive_left;
444 }
445
446
447 if ((zfor_sensitive_right - zback_sensitive_right) > length_feedthrough) {
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
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
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
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
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
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
522 zfor_sensitive_middle = zfor_sensitive_right - length_feedthrough;
523 }
524
525
526
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
533
534 G4UserLimits* uLimits = new G4UserLimits(8.5 * CLHEP::cm);
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
543 if (gcp.getMaterialDefinitionMode() == 2) {
544 G4String sName = "sWire";
545 const G4int jc = 0;
546 B2Vector3D wb0 = cdcgp.wireBackwardPosition(iSLayer, jc);
547
548 B2Vector3D wf0 = cdcgp.wireForwardPosition(iSLayer, jc);
549 G4double tAtZ0 = -wb0.
Z() / (wf0.Z() - wb0.Z());
551
552 const G4double epsl = 25.e-4;
553 G4double reductionBwd = (zback_sensitive_middle + epsl) / wb0.
Z();
554
555 wb0 = reductionBwd * (wb0 - wAtZ0) + wAtZ0;
556
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
563 G4Tubs* middleSensitiveSwireShape = new G4Tubs(sName, 0., sWireRadius, wireHalfLength, 0., 360. * CLHEP::deg);
564 G4LogicalVolume* middleSensitiveSwire = new G4LogicalVolume(middleSensitiveSwireShape, medTungsten, sName);
565
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
574
575 const G4double diameter = cdcgp.fieldWireDiameter();
576
577 const G4int nCells = cdcgp.nWiresInLayer(iSLayer);
578 const G4double dphi = M_PI / nCells;
580
581 for (int ic = 0; ic < nCells; ++ic) {
582
583 B2Vector3D wb = cdcgp.wireBackwardPosition(iSLayer, ic);
584 B2Vector3D wf = cdcgp.wireForwardPosition(iSLayer, ic);
585 G4double tAtZ02 = -wb.Z() / (wf.Z() - wb.Z());
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 B2Vector3D fMinusBInZX((wf - wb).X(), 0., (wf - wb).Z());
595 G4double thetaZX = asin((unitZ.Cross(fMinusBInZX)).Y() / fMinusBInZX.Mag());
596 G4RotationMatrix rotM;
597
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
605
606 new G4PVPlacement(G4Transform3D(rotM, xyz), middleSensitiveSwire, sName, middleSensitiveTube, false, ic);
607
608
610 G4double rF = rmax_sensitive_middle - 0.5 * diameter;
611
612 G4double phi = atan2(wbF.Y(), wbF.X());
613 wbF.SetX(rF * cos(phi));
614 wbF.SetY(rF * sin(phi));
615
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
637 new G4PVPlacement(G4Transform3D(rotM1, xyz), middleSensitiveFwire, fName, middleSensitiveTube, false, ic);
638 }
639
640
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
667 new G4PVPlacement(G4Transform3D(rotM2, xyz), middleSensitiveFwire, fName, middleSensitiveTube, false, ic + nCells);
668
669
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 }
699 }
700
701 }
702
703
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);
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
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);
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
752
754
755
756
757
759
760
761
762
764
765
766
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
799
800
801 G4LogicalVolume* logicalV = new G4LogicalVolume(boxShape, medAluminum, logicalName, 0, 0, 0);
802 if (id > 39 && id < 78)
803 logicalV = new G4LogicalVolume(boxShape, medCopper, logicalName, 0, 0, 0);
804 if ((id > 77 && id < 94) || (id > 131 && id < 146))
805 logicalV = new G4LogicalVolume(boxShape, medNEMA_G10_Plate, logicalName, 0, 0, 0);
806 if (id > 93 && id < 110)
807 logicalV = new G4LogicalVolume(tubeShape, medCopper, logicalName, 0, 0, 0);
808 if (id > 109 && id < 126)
809 logicalV = new G4LogicalVolume(tubeShape, medH2O, logicalName, 0, 0, 0);
810 if (id > 127 && id < 132)
811 logicalV = new G4LogicalVolume(boxShape, medHV, logicalName, 0, 0, 0);
812
813
814
815
816
817
818
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,
839 rot.rotateZ(phi * CLHEP::deg);
840 arm.rotateZ(phi * CLHEP::deg);
841 }
842
843 }
844
845
846
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
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,
892 rot.rotateZ(phi * CLHEP::deg);
893 arm.rotateZ(phi * CLHEP::deg);
894 }
895
896 }
897
898
899
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
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,
956 rot.rotateZ(phi * CLHEP::deg);
957 arm.rotateZ(phi * CLHEP::deg);
958 }
959
960 }
961
962
963
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
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,
1026 rot.rotateZ(phi * CLHEP::deg);
1027 arm.rotateZ(phi * CLHEP::deg);
1028 }
1029
1030 }
1031
1032
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
1070
1071 const double phi = 360.0 / ndiv;
1072
1073 G4RotationMatrix rot = G4RotationMatrix();
1074
1075
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,
1088 rot.rotateZ(phi * CLHEP::deg);
1089 arm.rotateZ(phi * CLHEP::deg);
1090 }
1091
1092 }
1093
1094
1096 }
DataType Z() const
access variable Z (= .at(2) without boundary check)
static CDCGeometryPar & Instance(const CDCGeometry *=nullptr)
Static method to get a reference to the CDCGeometryPar instance.
void createNeutronShields(const GearDir &content)
Create neutron shield from gearbox.
void createCover2s(const GearDir &content)
Create CDC cover2s from gear box.
void createMapper(G4LogicalVolume &topVolume)
Create the B-field mapper geometry (tentative function)
void createCovers(const GearDir &content)
Create CDC covers from gear box.
B2Vector3< double > B2Vector3D
typedef for common usage with double