91 {
92
93 m_sensitive = new CDCSensitiveDetector("CDCSensitiveDetector", (2 * 24)* CLHEP::eV, 10 * CLHEP::MeV);
94
95 const G4double realTemperture = (273.15 + 23.) * CLHEP::kelvin;
96 G4Material* medHelium = geometry::Materials::get("CDCHeGas");
97 G4Material* medEthane = geometry::Materials::get("CDCEthaneGas");
98 G4Material* medAluminum = geometry::Materials::get("Al");
99 G4Material* medTungsten = geometry::Materials::get("W");
100 G4Material* medCFRP = geometry::Materials::get("CFRP");
101 G4Material* medNEMA_G10_Plate = geometry::Materials::get("NEMA_G10_Plate");
102 G4Material* medGlue = geometry::Materials::get("CDCGlue");
103 G4Material* medAir = geometry::Materials::get("Air");
104
105 G4double h2odensity = 1.000 * CLHEP::g / CLHEP::cm3;
106 G4double a = 1.01 * CLHEP::g / CLHEP::mole;
107 G4Element* elH = new G4Element("Hydrogen", "H", 1., a);
108 a = 16.00 * CLHEP::g / CLHEP::mole;
109 G4Element* elO = new G4Element("Oxygen", "O", 8., a);
110 G4Material* medH2O = new G4Material("Water", h2odensity, 2);
111 medH2O->AddElement(elH, 2);
112 medH2O->AddElement(elO, 1);
113 G4Material* medCopper = geometry::Materials::get("Cu");
114 G4Material* medHV = geometry::Materials::get("CDCHVCable");
115
116
117
118
119
120 const double rmax_innerWall = geo.getFiducialRmin();
121 const double rmin_outerWall = geo.getFiducialRmax();
122 const double diameter_senseWire = geo.getSenseDiameter();
123 const double diameter_fieldWire = geo.getFieldDiameter();
124 const double num_senseWire = static_cast<double>(geo.getNSenseWires());
125 const double num_fieldWire = static_cast<double>(geo.getNFieldWires());
126 double totalCS = M_PI * (rmin_outerWall * rmin_outerWall - rmax_innerWall * rmax_innerWall);
127
128
129 double senseCS = M_PI * (diameter_senseWire / 2) * (diameter_senseWire / 2) * num_senseWire;
130
131
132 double fieldCS = M_PI * (diameter_fieldWire / 2) * (diameter_fieldWire / 2) * num_fieldWire;
133
134
135 const double denHelium = medHelium->GetDensity() / 2.0;
136 const double denEthane = medEthane->GetDensity() / 2.0;
137 const double denAluminum = medAluminum->GetDensity() * (fieldCS / totalCS);
138 const double denTungsten = medTungsten->GetDensity() * (senseCS / totalCS);
139 const double density = denHelium + denEthane + denAluminum + denTungsten;
140 G4Material* cdcMed = new G4Material("CDCGasWire", density, 4, kStateGas, realTemperture);
141 cdcMed->AddMaterial(medHelium, denHelium / density);
142 cdcMed->AddMaterial(medEthane, denEthane / density);
143 cdcMed->AddMaterial(medTungsten, denTungsten / density);
144 cdcMed->AddMaterial(medAluminum, denAluminum / density);
145
146 G4Material* cdcMedGas = cdcMed;
147
148 CDCGeometryPar& cdcgp = CDCGeometryPar::Instance(&geo);
149 const CDCGeoControlPar& gcp = CDCGeoControlPar::getInstance();
150
151
152
153 if (gcp.getMaterialDefinitionMode() == 2) {
154 const double density2 = denHelium + denEthane;
155 cdcMedGas = new G4Material("CDCRealGas", density2, 2, kStateGas, realTemperture);
156 cdcMedGas->AddMaterial(medHelium, denHelium / density2);
157 cdcMedGas->AddMaterial(medEthane, denEthane / density2);
158 }
159
160 if (gcp.getPrintMaterialTable()) {
161 G4cout << *(G4Material::GetMaterialTable());
162 }
163
164 const auto& mother = geo.getMotherVolume();
165 const auto& motherRmin = mother.getRmin();
166 const auto& motherRmax = mother.getRmax();
167 const auto& motherZ = mother.getZ();
168 G4Polycone* solid_cdc =
169 new G4Polycone("solidCDC", 0 * CLHEP::deg, 360.* CLHEP::deg,
170 mother.getNNodes(), motherZ.data(),
171 motherRmin.data(), motherRmax.data());
172 m_logicalCDC = new G4LogicalVolume(solid_cdc, medAir, "logicalCDC", 0, 0, 0);
173 m_physicalCDC = new G4PVPlacement(0, G4ThreeVector(geo.getGlobalOffsetX() * CLHEP::cm,
174 geo.getGlobalOffsetY() * CLHEP::cm,
175 geo.getGlobalOffsetZ() * CLHEP::cm), m_logicalCDC,
176 "physicalCDC", &topVolume, false, 0);
177
178
179 G4Region* aRegion = new G4Region("CDCEnvelope");
180 m_logicalCDC->SetRegion(aRegion);
181 aRegion->AddRootLogicalVolume(m_logicalCDC);
182
183 m_VisAttributes.push_back(new G4VisAttributes(true, G4Colour(0., 1., 0.)));
184 for (const auto& wall : geo.getOuterWalls()) {
185 const int iOuterWall = wall.getId();
186 const string wallName = wall.getName();
187 const double wallRmin = wall.getRmin();
188 const double wallRmax = wall.getRmax();
189 const double wallZfwd = wall.getZfwd();
190 const double wallZbwd = wall.getZbwd();
191 const double length = (wallZfwd - wallZbwd) / 2.0;
192
193
194 G4Material* medWall;
195 if (strstr((wallName).c_str(), "MiddleWall") != nullptr) {
196 medWall = medCFRP;
197 } else {
198 medWall = medAluminum;
199 }
200 G4Tubs* outerWallTubeShape = new G4Tubs("solid" + wallName, wallRmin * CLHEP::cm,
201 wallRmax * CLHEP::cm, length * CLHEP::cm, 0 * CLHEP::deg, 360.*CLHEP::deg);
202
203 G4LogicalVolume* outerWallTube = new G4LogicalVolume(outerWallTubeShape, medWall, "solid" + wallName, 0, 0, 0);
204 outerWallTube->SetVisAttributes(m_VisAttributes.back());
205 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (length + wallZbwd)*CLHEP::cm), outerWallTube, "logical" + wallName,
206 m_logicalCDC, false, iOuterWall);
207 }
208
209
210 m_VisAttributes.push_back(new G4VisAttributes(true, G4Colour(0., 1., 0.)));
211 for (const auto& wall : geo.getInnerWalls()) {
212 const string wallName = wall.getName();
213 const double wallRmin = wall.getRmin();
214 const double wallRmax = wall.getRmax();
215 const double wallZfwd = wall.getZfwd();
216 const double wallZbwd = wall.getZbwd();
217 const double length = (wallZfwd - wallZbwd) / 2.0;
218 const int iInnerWall = wall.getId();
219
220 G4Material* medWall;
221 if (strstr(wallName.c_str(), "MiddleWall") != nullptr) {
222 medWall = medCFRP;
223 } else if (strstr(wallName.c_str(), "MiddleGlue") != nullptr) {
224 medWall = medGlue;
225 } else {
226 medWall = medAluminum;
227 }
228
229 G4Tubs* innerWallTubeShape = new G4Tubs("solid" + wallName, wallRmin * CLHEP::cm,
230 wallRmax * CLHEP::cm, length * CLHEP::cm, 0 * CLHEP::deg, 360.*CLHEP::deg);
231 G4LogicalVolume* innerWallTube = new G4LogicalVolume(innerWallTubeShape, medWall, "logical" + wallName, 0, 0, 0);
232 innerWallTube->SetVisAttributes(m_VisAttributes.back());
233 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (length + wallZbwd)*CLHEP::cm), innerWallTube, "physical" + wallName,
234 m_logicalCDC, false, iInnerWall);
235
236
237 }
238
239
240
241
242
243
244 const uint nSLayer = geo.getNSenseLayers();
245 const double length_feedthrough = geo.getFeedthroughLength();
246 for (uint iSLayer = 0; iSLayer < nSLayer; ++iSLayer) {
247
248 double rmin_sensitive_left, rmax_sensitive_left;
249 double rmin_sensitive_middle, rmax_sensitive_middle;
250 double rmin_sensitive_right, rmax_sensitive_right;
251 double zback_sensitive_left, zfor_sensitive_left;
252 double zback_sensitive_middle, zfor_sensitive_middle;
253 double zback_sensitive_right, zfor_sensitive_right;
254
255 if (not getEndplateInformation(geo, iSLayer,
256 rmin_sensitive_left, rmax_sensitive_left, zback_sensitive_left, zfor_sensitive_left,
257 rmin_sensitive_middle, rmax_sensitive_middle, zback_sensitive_middle, zfor_sensitive_middle,
258 rmin_sensitive_right, rmax_sensitive_right, zback_sensitive_right, zfor_sensitive_right)) {
259 continue;
260 }
261
262
263 if ((zfor_sensitive_left - zback_sensitive_left) > length_feedthrough) {
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280 G4Tubs* leftTubeShape = new G4Tubs((boost::format("solidCDCLayer_%1%_leftTube") % iSLayer).str().c_str(),
281 rmin_sensitive_left * CLHEP::cm,
282 rmax_sensitive_left * CLHEP::cm, length_feedthrough * CLHEP::cm / 2.0, 0 * CLHEP::deg, 360.*CLHEP::deg);
283 G4LogicalVolume* leftTube = new G4LogicalVolume(leftTubeShape, cdcMed,
284 (boost::format("logicalCDCLayer_%1%_leftTube") % iSLayer).str().c_str(), 0, 0, 0);
285 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (zback_sensitive_left + length_feedthrough / 2.0)*CLHEP::cm), leftTube,
286 (boost::format("physicalCDCLayer_%1%_leftTube") % iSLayer).str().c_str(), m_logicalCDC, false, iSLayer);
287
288 G4Tubs* leftSensitiveTubeShape = new G4Tubs((boost::format("solidSD_CDCLayer_%1%_left") % iSLayer).str().c_str(),
289 rmin_sensitive_left * CLHEP::cm, rmax_sensitive_left * CLHEP::cm,
290 (zfor_sensitive_left - zback_sensitive_left - length_feedthrough)*CLHEP::cm / 2.0, 0 * CLHEP::deg, 360.*CLHEP::deg);
291 G4LogicalVolume* leftSensitiveTube = new G4LogicalVolume(leftSensitiveTubeShape, cdcMed,
292 (boost::format("logicalSD_CDCLayer_%1%_left") % iSLayer).str().c_str(), 0, 0, 0);
293 leftSensitiveTube->SetSensitiveDetector(m_sensitive);
294 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (zfor_sensitive_left + zback_sensitive_left + length_feedthrough)*CLHEP::cm / 2.0),
295 leftSensitiveTube, (boost::format("physicalSD_CDCLayer_%1%_left") % iSLayer).str().c_str(), m_logicalCDC, false, iSLayer);
296 } else {
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313 G4Tubs* leftTubeShape = new G4Tubs((boost::format("solidCDCLayer_%1%_leftTube") % iSLayer).str().c_str(),
314 rmin_sensitive_left * CLHEP::cm,
315 rmax_sensitive_left * CLHEP::cm, (zfor_sensitive_left - zback_sensitive_left)*CLHEP::cm / 2.0, 0 * CLHEP::deg, 360.*CLHEP::deg);
316 G4LogicalVolume* leftTube = new G4LogicalVolume(leftTubeShape, cdcMed,
317 (boost::format("logicalCDCLayer_%1%_leftTube") % iSLayer).str().c_str(), 0, 0, 0);
318 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (zfor_sensitive_left + zback_sensitive_left)*CLHEP::cm / 2.0), leftTube,
319 (boost::format("physicalCDCLayer_%1%_leftTube") % iSLayer).str().c_str(), m_logicalCDC, false, iSLayer);
320
321
322
323 G4Tubs* leftMidTubeShape = new G4Tubs((boost::format("solidCDCLayer_%1%_leftMidTube") % iSLayer).str().c_str(),
324 rmin_sensitive_middle * CLHEP::cm, rmax_sensitive_middle * CLHEP::cm,
325 (length_feedthrough - zfor_sensitive_left + zback_sensitive_left)*CLHEP::cm / 2.0, 0 * CLHEP::deg, 360.*CLHEP::deg);
326 G4LogicalVolume* leftMidTube = new G4LogicalVolume(leftMidTubeShape, cdcMed,
327 (boost::format("logicalCDCLayer_%1%_leftMidTube") % iSLayer).str().c_str(), 0, 0, 0);
328
329 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (length_feedthrough + zfor_sensitive_left + zback_sensitive_left)*CLHEP::cm / 2.0),
330 leftMidTube, (boost::format("physicalCDCLayer_%1%_leftMidTube") % iSLayer).str().c_str(), m_logicalCDC, false, iSLayer);
331
332
333 zback_sensitive_middle = length_feedthrough + zback_sensitive_left;
334 }
335
336
337 if ((zfor_sensitive_right - zback_sensitive_right) > length_feedthrough) {
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354 G4Tubs* rightTubeShape = new G4Tubs((boost::format("solidCDCLayer_%1%_rightTube") % iSLayer).str().c_str(),
355 rmin_sensitive_right * CLHEP::cm, rmax_sensitive_right * CLHEP::cm, length_feedthrough * CLHEP::cm / 2.0, 0 * CLHEP::deg,
356 360.*CLHEP::deg);
357 G4LogicalVolume* rightTube = new G4LogicalVolume(rightTubeShape, cdcMed,
358 (boost::format("logicalCDCLayer_%1%_rightTube") % iSLayer).str().c_str(), 0, 0, 0);
359
360 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (zfor_sensitive_right - length_feedthrough / 2.0)*CLHEP::cm), rightTube,
361 (boost::format("physicalCDCLayer_%1%_rightTube") % iSLayer).str().c_str(), m_logicalCDC, false, iSLayer);
362
363
364
365 G4Tubs* rightSensitiveTubeShape = new G4Tubs((boost::format("solidSD_CDCLayer_%1%_right") % iSLayer).str().c_str(),
366 rmin_sensitive_right * CLHEP::cm, rmax_sensitive_right * CLHEP::cm,
367 (zfor_sensitive_right - zback_sensitive_right - length_feedthrough)*CLHEP::cm / 2.0, 0 * CLHEP::deg, 360.*CLHEP::deg);
368 G4LogicalVolume* rightSensitiveTube = new G4LogicalVolume(rightSensitiveTubeShape, cdcMed,
369 (boost::format("logicalSD_CDCLayer_%1%_right") % iSLayer).str().c_str(), 0, 0, 0);
370 rightSensitiveTube->SetSensitiveDetector(m_sensitive);
371
372 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (zfor_sensitive_right + zback_sensitive_right - length_feedthrough)*CLHEP::cm / 2.0),
373 rightSensitiveTube, (boost::format("physicalSD_CDCLayer_%1%_right") % iSLayer).str().c_str(), m_logicalCDC, false, iSLayer);
374
375 } else {
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392 G4Tubs* rightTubeShape = new G4Tubs((boost::format("solidCDCLayer_%1%_rightTube") % iSLayer).str().c_str(),
393 rmin_sensitive_right * CLHEP::cm, rmax_sensitive_right * CLHEP::cm, (zfor_sensitive_right - zback_sensitive_right)*CLHEP::cm / 2.0,
394 0 * CLHEP::deg, 360.*CLHEP::deg);
395 G4LogicalVolume* rightTube = new G4LogicalVolume(rightTubeShape, cdcMed,
396 (boost::format("logicalCDCLayer_%1%_rightTube") % iSLayer).str().c_str(), 0, 0, 0);
397
398 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (zfor_sensitive_right + zback_sensitive_right)*CLHEP::cm / 2.0), rightTube,
399 (boost::format("physicalCDCLayer_%1%_rightTube") % iSLayer).str().c_str(), m_logicalCDC, false, iSLayer);
400
401
402
403 G4Tubs* rightMidTubeShape = new G4Tubs((boost::format("solidCDCLayer_%1%_rightMidTube") % iSLayer).str().c_str(),
404 rmin_sensitive_middle * CLHEP::cm, rmax_sensitive_middle * CLHEP::cm,
405 (length_feedthrough - zfor_sensitive_right + zback_sensitive_right)*CLHEP::cm / 2.0, 0 * CLHEP::deg, 360.*CLHEP::deg);
406 G4LogicalVolume* rightMidTube = new G4LogicalVolume(rightMidTubeShape, cdcMed,
407 (boost::format("logicalCDCLayer_%1%_rightMidTube") % iSLayer).str().c_str(), 0, 0, 0);
408 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (zback_sensitive_right - length_feedthrough + zfor_sensitive_right)*CLHEP::cm / 2.0),
409 rightMidTube, (boost::format("physicalCDCLayer_%1%_rightMidTube") % iSLayer).str().c_str(), m_logicalCDC, false, iSLayer);
410
411
412 zfor_sensitive_middle = zfor_sensitive_right - length_feedthrough;
413 }
414
415
416
417 G4Tubs* middleSensitiveTubeShape = new G4Tubs((boost::format("solidSD_CDCLayer_%1%_middle") % iSLayer).str().c_str(),
418 rmin_sensitive_middle * CLHEP::cm, rmax_sensitive_middle * CLHEP::cm,
419 (zfor_sensitive_middle - zback_sensitive_middle)*CLHEP::cm / 2.0, 0 * CLHEP::deg, 360.*CLHEP::deg);
420 G4LogicalVolume* middleSensitiveTube = new G4LogicalVolume(middleSensitiveTubeShape, cdcMedGas,
421 (boost::format("logicalSD_CDCLayer_%1%_middle") % iSLayer).str().c_str(), 0, 0, 0);
422
423
424 G4UserLimits* uLimits = new G4UserLimits(8.5 * CLHEP::cm);
425 m_userLimits.push_back(uLimits);
426 middleSensitiveTube->SetUserLimits(uLimits);
427 middleSensitiveTube->SetSensitiveDetector(m_sensitive);
428
429 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (zfor_sensitive_middle + zback_sensitive_middle)*CLHEP::cm / 2.0), middleSensitiveTube,
430 (boost::format("physicalSD_CDCLayer_%1%_middle") % iSLayer).str().c_str(), m_logicalCDC, false, iSLayer);
431
432
433 if (gcp.getMaterialDefinitionMode() == 2) {
434 G4String sName = "sWire";
435 const G4int jc = 0;
436 B2Vector3D wb0 = cdcgp.wireBackwardPosition(iSLayer, jc);
437
438 B2Vector3D wf0 = cdcgp.wireForwardPosition(iSLayer, jc);
439 G4double tAtZ0 = -wb0.
Z() / (wf0.Z() - wb0.Z());
441
442 const G4double epsl = 25.e-4;
443 G4double reductionBwd = (zback_sensitive_middle + epsl) / wb0.
Z();
444
445 wb0 = reductionBwd * (wb0 - wAtZ0) + wAtZ0;
446
447 G4double reductionFwd = (zfor_sensitive_middle - epsl) / wf0.Z();
448 wf0 = reductionFwd * (wf0 - wAtZ0) + wAtZ0;
449
450 const G4double wireHalfLength = 0.5 * (wf0 - wb0).Mag() * CLHEP::cm;
451 const G4double sWireRadius = 0.5 * cdcgp.senseWireDiameter() * CLHEP::cm;
452
453 G4Tubs* middleSensitiveSwireShape = new G4Tubs(sName, 0., sWireRadius, wireHalfLength, 0., 360. * CLHEP::deg);
454 G4LogicalVolume* middleSensitiveSwire = new G4LogicalVolume(middleSensitiveSwireShape, medTungsten, sName);
455
456 middleSensitiveSwire->SetVisAttributes(m_VisAttributes.front());
457
458 G4String fName = "fWire";
459 const G4double fWireRadius = 0.5 * cdcgp.fieldWireDiameter() * CLHEP::cm;
460 G4Tubs* middleSensitiveFwireShape = new G4Tubs(fName, 0., fWireRadius, wireHalfLength, 0., 360. * CLHEP::deg);
461 G4LogicalVolume* middleSensitiveFwire = new G4LogicalVolume(middleSensitiveFwireShape, medAluminum, fName);
462
463 middleSensitiveFwire->SetVisAttributes(m_VisAttributes.front());
464
465 const G4double diameter = cdcgp.fieldWireDiameter();
466
467 const G4int nCells = cdcgp.nWiresInLayer(iSLayer);
468 const G4double dphi = M_PI / nCells;
470
471 for (int ic = 0; ic < nCells; ++ic) {
472
473 B2Vector3D wb = cdcgp.wireBackwardPosition(iSLayer, ic);
474 B2Vector3D wf = cdcgp.wireForwardPosition(iSLayer, ic);
475 G4double tAtZ02 = -wb.
Z() / (wf.Z() - wb.Z());
477 G4double reductionBwd2 = (zback_sensitive_middle + epsl) / wb.
Z();
478 wb = reductionBwd2 * (wb - wAtZ02) + wAtZ02;
479 G4double reductionFwd2 = (zfor_sensitive_middle - epsl) / wf.Z();
480 wf = reductionFwd2 * (wf - wAtZ02) + wAtZ02;
481
482 G4double thetaYZ = -asin((wf - wb).Y() / (wf - wb).Mag());
483
484 B2Vector3D fMinusBInZX((wf - wb).X(), 0., (wf - wb).Z());
485 G4double thetaZX = asin((unitZ.Cross(fMinusBInZX)).Y() / fMinusBInZX.Mag());
486 G4RotationMatrix rotM;
487
488 rotM.rotateX(thetaYZ * CLHEP::rad);
489 rotM.rotateY(thetaZX * CLHEP::rad);
490
491 G4ThreeVector xyz(0.5 * (wb.X() + wf.X()) * CLHEP::cm,
492 0.5 * (wb.Y() + wf.Y()) * CLHEP::cm, 0.);
493
494
495
496 new G4PVPlacement(G4Transform3D(rotM, xyz), middleSensitiveSwire, sName, middleSensitiveTube, false, ic);
497
498
500 G4double rF = rmax_sensitive_middle - 0.5 * diameter;
501
502 G4double phi = atan2(wbF.Y(), wbF.X());
503 wbF.SetX(rF * cos(phi));
504 wbF.SetY(rF * sin(phi));
505
507 rF = rmax_sensitive_middle - 0.5 * diameter;
508 phi = atan2(wfF.Y(), wfF.X());
509 wfF.SetX(rF * cos(phi));
510 wfF.SetY(rF * sin(phi));
511
512 thetaYZ = -asin((wfF - wbF).Y() / (wfF - wbF).Mag());
513
514 fMinusBInZX = wfF - wbF;
515 fMinusBInZX.SetY(0.);
516 thetaZX = asin((unitZ.Cross(fMinusBInZX)).Y() / fMinusBInZX.Mag());
517
518 G4RotationMatrix rotM1;
519 rotM1.rotateX(thetaYZ * CLHEP::rad);
520 rotM1.rotateY(thetaZX * CLHEP::rad);
521
522 xyz.setX(0.5 * (wbF.X() + wfF.X()) * CLHEP::cm);
523 xyz.setY(0.5 * (wbF.Y() + wfF.Y()) * CLHEP::cm);
524
525 if (iSLayer != nSLayer - 1) {
526
527 new G4PVPlacement(G4Transform3D(rotM1, xyz), middleSensitiveFwire, fName, middleSensitiveTube, false, ic);
528 }
529
530
531 wbF = wb;
532 rF = wbF.Perp();
533 phi = atan2(wbF.Y(), wbF.X());
534 wbF.SetX(rF * cos(phi + dphi));
535 wbF.SetY(rF * sin(phi + dphi));
536
537 wfF = wf;
538 rF = wfF.Perp();
539 phi = atan2(wfF.Y(), wfF.X());
540 wfF.SetX(rF * cos(phi + dphi));
541 wfF.SetY(rF * sin(phi + dphi));
542
543 thetaYZ = -asin((wfF - wbF).Y() / (wfF - wbF).Mag());
544
545 fMinusBInZX = wfF - wbF;
546 fMinusBInZX.SetY(0.);
547 thetaZX = asin((unitZ.Cross(fMinusBInZX)).Y() / fMinusBInZX.Mag());
548
549 G4RotationMatrix rotM2;
550 rotM2.rotateX(thetaYZ * CLHEP::rad);
551 rotM2.rotateY(thetaZX * CLHEP::rad);
552
553 xyz.setX(0.5 * (wbF.X() + wfF.X()) * CLHEP::cm);
554 xyz.setY(0.5 * (wbF.Y() + wfF.Y()) * CLHEP::cm);
555
556
557 new G4PVPlacement(G4Transform3D(rotM2, xyz), middleSensitiveFwire, fName, middleSensitiveTube, false, ic + nCells);
558
559
560 wbF = wb;
561 rF = rmax_sensitive_middle - 0.5 * diameter;
562 phi = atan2(wbF.Y(), wbF.X());
563 wbF.SetX(rF * cos(phi + dphi));
564 wbF.SetY(rF * sin(phi + dphi));
565
566 wfF = wf;
567 rF = rmax_sensitive_middle - 0.5 * diameter;
568 phi = atan2(wfF.Y(), wfF.X());
569 wfF.SetX(rF * cos(phi + dphi));
570 wfF.SetY(rF * sin(phi + dphi));
571
572 thetaYZ = -asin((wfF - wbF).Y() / (wfF - wbF).Mag());
573
574 fMinusBInZX = wfF - wbF;
575 fMinusBInZX.SetY(0.);
576 thetaZX = asin((unitZ.Cross(fMinusBInZX)).Y() / fMinusBInZX.Mag());
577
578 G4RotationMatrix rotM3;
579 rotM3.rotateX(thetaYZ * CLHEP::rad);
580 rotM3.rotateY(thetaZX * CLHEP::rad);
581
582 xyz.setX(0.5 * (wbF.X() + wfF.X()) * CLHEP::cm);
583 xyz.setY(0.5 * (wbF.Y() + wfF.Y()) * CLHEP::cm);
584
585 if (iSLayer != nSLayer - 1) {
586 new G4PVPlacement(G4Transform3D(rotM3, xyz), middleSensitiveFwire, fName, middleSensitiveTube, false, ic + 2 * nCells);
587 }
588 }
589 }
590
591 }
592
593
594
595
596 m_VisAttributes.push_back(new G4VisAttributes(true, G4Colour(1., 1., 0.)));
597 for (const auto& endplate : geo.getEndPlates()) {
598 for (const auto& epLayer : endplate.getEndPlateLayers()) {
599 const int iEPLayer = epLayer.getILayer();
600 const string name = epLayer.getName();
601 const double rmin = epLayer.getRmin();
602 const double rmax = epLayer.getRmax();
603 const double zbwd = epLayer.getZbwd();
604 const double zfwd = epLayer.getZfwd();
605 const double length = (zfwd - zbwd) / 2.0;
606
607 G4Tubs* tube = new G4Tubs("solidCDCEndplate" + name, rmin * CLHEP::cm,
608 rmax * CLHEP::cm, length * CLHEP::cm, 0 * CLHEP::deg, 360.*CLHEP::deg);
609 G4LogicalVolume* logical = new G4LogicalVolume(tube, Materials::get("G4_Al"),
610 "logicalCDCEndplate" + name, 0, 0);
611 logical->SetVisAttributes(m_VisAttributes.back());
612 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (zfwd + zbwd)*CLHEP::cm / 2.0), logical,
613 "physicalCDCEndplate" + name, m_logicalCDC, false, iEPLayer);
614
615 }
616 }
617
618
619
620 for (const auto& frontend : geo.getFrontends()) {
621
622 const int iEB = frontend.getId();
623 const double ebInnerR = frontend.getRmin();
624 const double ebOuterR = frontend.getRmax();
625 const double ebBZ = frontend.getZbwd();
626 const double ebFZ = frontend.getZfwd();
627
628 G4Tubs* ebTubeShape = new G4Tubs((boost::format("solidSD_ElectronicsBoard_Layer%1%") % iEB).str().c_str(), ebInnerR * CLHEP::cm,
629 ebOuterR * CLHEP::cm, (ebFZ - ebBZ)*CLHEP::cm / 2.0, 0 * CLHEP::deg, 360.*CLHEP::deg);
630
631 G4LogicalVolume* ebTube = new G4LogicalVolume(ebTubeShape, medNEMA_G10_Plate,
632 (boost::format("logicalSD_ElectronicsBoard_Layer%1%") % iEB).str().c_str(), 0, 0, 0);
633 if (!m_bkgsensitive) m_bkgsensitive = new BkgSensitiveDetector("CDC", iEB);
634 ebTube->SetSensitiveDetector(m_bkgsensitive);
635 ebTube->SetVisAttributes(m_VisAttributes.back());
636 new G4PVPlacement(0, G4ThreeVector(0.0, 0.0, (ebFZ + ebBZ)*CLHEP::cm / 2.0), ebTube,
637 (boost::format("physicalSD_ElectronicsBoard_Layer%1%") % iEB).str().c_str(), m_logicalCDC, false, iEB);
638 }
639
640
641
642
643 createNeutronShields(geo);
644
645
646
647
648 createCovers(geo);
649
650
651
652
653 createCover2s(geo);
654
655
656
657
658 for (const auto& rib : geo.getRibs()) {
659
660 const int id = rib.getId();
661 const double length = rib.getLength();
662 const double width = rib.getWidth();
663 const double thick = rib.getThick();
664 const double rotx = rib.getRotX();
665 const double roty = rib.getRotY();
666 const double rotz = rib.getRotZ();
667 const double x = rib.getX();
668 const double y = rib.getY();
669 const double z = rib.getZ();
670 const int offset = rib.getOffset();
671 const int ndiv = rib.getNDiv();
672
673 const string solidName = "solidRib" + to_string(id);
674 const string logicalName = "logicalRib" + to_string(id);
675 G4Box* boxShape = new G4Box(solidName, 0.5 * length * CLHEP::cm,
676 0.5 * width * CLHEP::cm,
677 0.5 * thick * CLHEP::cm);
678
679 const double rmax = 0.5 * length;
680 const double rmin = max((rmax - thick), 0.);
681 G4Tubs* tubeShape = new G4Tubs(solidName,
682 rmin * CLHEP::cm,
683 rmax * CLHEP::cm,
684 0.5 * width * CLHEP::cm,
685 0.,
686 360. * CLHEP::deg);
687
688
689
690
691 G4LogicalVolume* logicalV = new G4LogicalVolume(boxShape, medAluminum, logicalName, 0, 0, 0);
692 if (id > 39 && id < 78)
693 logicalV = new G4LogicalVolume(boxShape, medCopper, logicalName, 0, 0, 0);
694 if ((id > 77 && id < 94) || (id > 131 && id < 146))
695 logicalV = new G4LogicalVolume(boxShape, medNEMA_G10_Plate, logicalName, 0, 0, 0);
696 if (id > 93 && id < 110)
697 logicalV = new G4LogicalVolume(tubeShape, medCopper, logicalName, 0, 0, 0);
698 if (id > 109 && id < 126)
699 logicalV = new G4LogicalVolume(tubeShape, medH2O, logicalName, 0, 0, 0);
700 if (id > 127 && id < 132)
701 logicalV = new G4LogicalVolume(boxShape, medHV, logicalName, 0, 0, 0);
702
703
704
705
706
707
708
709 logicalV->SetVisAttributes(m_VisAttributes.back());
710
711 const double phi = 360.0 / ndiv;
712
713 G4RotationMatrix rot = G4RotationMatrix();
714 double dz = thick;
715 if (id > 93 && id < 126) dz = 0;
716
717 G4ThreeVector arm(x * CLHEP::cm, y * CLHEP::cm, z * CLHEP::cm - dz * CLHEP::cm / 2.0);
718 rot.rotateX(rotx);
719 rot.rotateY(roty);
720 rot.rotateZ(rotz);
721 if (offset) {
722 rot.rotateZ(0.5 * phi * CLHEP::deg);
723 arm.rotateZ(0.5 * phi * CLHEP::deg);
724 }
725 for (int i = 0; i < ndiv; ++i) {
726 const string physicalName = "physicalRib_" + to_string(id) + " " + to_string(i);
727 new G4PVPlacement(G4Transform3D(rot, arm), logicalV,
728 physicalName.c_str(), m_logicalCDC, false, id);
729 rot.rotateZ(phi * CLHEP::deg);
730 arm.rotateZ(phi * CLHEP::deg);
731 }
732
733 }
734
735
736
737
738 for (const auto& rib2 : geo.getRib2s()) {
739
740 const int id = rib2.getId();
741 const double length = rib2.getLength();
742 const double width = rib2.getWidth();
743 const double thick = rib2.getThick();
744 const double width2 = rib2.getWidth2();
745 const double thick2 = rib2.getThick2();
746 const double rotx = rib2.getRotX();
747 const double roty = rib2.getRotY();
748 const double rotz = rib2.getRotZ();
749 const double x = rib2.getX();
750 const double y = rib2.getY();
751 const double z = rib2.getZ();
752 const int ndiv = rib2.getNDiv();
753
754 const string solidName = "solidRib2" + to_string(id);
755 const string logicalName = "logicalRib2" + to_string(id);
756 G4Trd* trdShape = new G4Trd(solidName,
757 0.5 * thick * CLHEP::cm,
758 0.5 * thick2 * CLHEP::cm,
759 0.5 * width * CLHEP::cm,
760 0.5 * width2 * CLHEP::cm,
761 0.5 * length * CLHEP::cm);
762
763 G4LogicalVolume* logicalV = new G4LogicalVolume(trdShape, medAluminum, logicalName, 0, 0, 0);
764
765 if (id > 0)
766 logicalV = new G4LogicalVolume(trdShape, medCopper, logicalName, 0, 0, 0);
767
768 logicalV->SetVisAttributes(m_VisAttributes.back());
769
770 const double phi = 360.0 / ndiv;
771
772 G4RotationMatrix rot = G4RotationMatrix();
773 G4ThreeVector arm(x * CLHEP::cm, y * CLHEP::cm, z * CLHEP::cm - thick * CLHEP::cm / 2.0);
774
775 rot.rotateX(rotx);
776 rot.rotateY(roty);
777 rot.rotateZ(rotz);
778 for (int i = 0; i < ndiv; ++i) {
779 const string physicalName = "physicalRib2_" + to_string(id) + " " + to_string(i);
780 new G4PVPlacement(G4Transform3D(rot, arm), logicalV,
781 physicalName.c_str(), m_logicalCDC, false, id);
782 rot.rotateZ(phi * CLHEP::deg);
783 arm.rotateZ(phi * CLHEP::deg);
784 }
785
786 }
787
788
789
790
791 for (const auto& rib3 : geo.getRib3s()) {
792
793 const int id = rib3.getId();
794 const double length = rib3.getLength();
795 const double width = rib3.getWidth();
796 const double thick = rib3.getThick();
797 const double r = rib3.getR();
798 const double x = rib3.getX();
799 const double y = rib3.getY();
800 const double z = rib3.getZ();
801 const double rx = rib3.getRx();
802 const double ry = rib3.getRy();
803 const double rz = rib3.getRz();
804 const int offset = rib3.getOffset();
805 const int ndiv = rib3.getNDiv();
806
807 const string logicalName = "logicalRib3" + to_string(id);
808 G4VSolid* boxShape = new G4Box("Block",
809 0.5 * length * CLHEP::cm,
810 0.5 * width * CLHEP::cm,
811 0.5 * thick * CLHEP::cm);
812 G4VSolid* tubeShape = new G4Tubs("Hole",
813 0.,
814 r * CLHEP::cm,
815 width * CLHEP::cm,
816 0. * CLHEP::deg,
817 360. * CLHEP::deg);
818
819 G4RotationMatrix rotsub = G4RotationMatrix();
820 rotsub.rotateX(90. * CLHEP::deg);
821 G4ThreeVector trnsub(rx * CLHEP::cm - x * CLHEP::cm, ry * CLHEP::cm - y * CLHEP::cm,
822 rz * CLHEP::cm - z * CLHEP::cm + 0.5 * thick * CLHEP::cm);
823 G4VSolid* coolingBlock = new G4SubtractionSolid("Block-Hole",
824 boxShape,
825 tubeShape,
826 G4Transform3D(rotsub,
827 trnsub));
828
829 G4LogicalVolume* logicalV = new G4LogicalVolume(coolingBlock, medCopper, logicalName, 0, 0, 0);
830
831 logicalV->SetVisAttributes(m_VisAttributes.back());
832
833 const double phi = 360.0 / ndiv;
834
835 G4RotationMatrix rot = G4RotationMatrix();
836 G4ThreeVector arm(x * CLHEP::cm, y * CLHEP::cm, z * CLHEP::cm - thick * CLHEP::cm / 2.0);
837
838 if (offset) {
839 rot.rotateZ(0.5 * phi * CLHEP::deg);
840 arm.rotateZ(0.5 * phi * CLHEP::deg);
841 }
842 for (int i = 0; i < ndiv; ++i) {
843 const string physicalName = "physicalRib3_" + to_string(id) + " " + to_string(i);
844 new G4PVPlacement(G4Transform3D(rot, arm), logicalV,
845 physicalName.c_str(), m_logicalCDC, false, id);
846 rot.rotateZ(phi * CLHEP::deg);
847 arm.rotateZ(phi * CLHEP::deg);
848 }
849
850 }
851
852
853
854
855 for (const auto& rib4 : geo.getRib4s()) {
856
857 const int id = rib4.getId();
858 const double length = rib4.getLength();
859 const double width = rib4.getWidth();
860 const double thick = rib4.getThick();
861 const double length2 = rib4.getLength2();
862 const double width2 = rib4.getWidth2();
863 const double thick2 = rib4.getThick2();
864 const double x = rib4.getX();
865 const double y = rib4.getY();
866 const double z = rib4.getZ();
867 const double x2 = rib4.getX2();
868 const double y2 = rib4.getY2();
869 const double z2 = rib4.getZ2();
870 const int offset = rib4.getOffset();
871 const int ndiv = rib4.getNDiv();
872
873 const string logicalName = "logicalRib4" + to_string(id);
874 G4VSolid* baseShape = new G4Box("Base",
875 0.5 * length * CLHEP::cm,
876 0.5 * width * CLHEP::cm,
877 0.5 * thick * CLHEP::cm);
878 G4VSolid* sqShape = new G4Box("Sq",
879 0.5 * length2 * CLHEP::cm,
880 0.5 * width2 * CLHEP::cm,
881 0.5 * thick2 * CLHEP::cm);
882
883 G4RotationMatrix rotsub = G4RotationMatrix();
884 double dzc = (z2 - thick2 / 2.) - (z - thick / 2.);
885 G4ThreeVector trnsub(x2 * CLHEP::cm - x * CLHEP::cm,
886 y2 * CLHEP::cm - y * CLHEP::cm,
887 dzc * CLHEP::cm);
888 G4VSolid* sqHoleBase = new G4SubtractionSolid("Box-Sq",
889 baseShape,
890 sqShape,
891 G4Transform3D(rotsub,
892 trnsub)
893 );
894
895 G4LogicalVolume* logicalV = new G4LogicalVolume(sqHoleBase, medCopper, logicalName, 0, 0, 0);
896 if (id < 19) {
897 logicalV = new G4LogicalVolume(sqHoleBase, medNEMA_G10_Plate, logicalName, 0, 0, 0);
898 BkgSensitiveDetector* sensitiveDetector =
899 new BkgSensitiveDetector("CDC", 2000 + id);
900 logicalV->SetSensitiveDetector(sensitiveDetector);
901 m_BkgSensitiveRib4.push_back(sensitiveDetector);
902 }
903
904 logicalV->SetVisAttributes(m_VisAttributes.back());
905
906 const double phi = 360.0 / ndiv;
907
908 G4RotationMatrix rot = G4RotationMatrix();
909 G4ThreeVector arm(x * CLHEP::cm, y * CLHEP::cm, z * CLHEP::cm - thick * CLHEP::cm / 2.0);
910
911 if (offset) {
912 rot.rotateZ(0.5 * phi * CLHEP::deg);
913 arm.rotateZ(0.5 * phi * CLHEP::deg);
914 }
915 for (int i = 0; i < ndiv; ++i) {
916 const string physicalName = "physicalRib4_" + to_string(id) + " " + to_string(i);
917 new G4PVPlacement(G4Transform3D(rot, arm), logicalV,
918 physicalName.c_str(), m_logicalCDC, false, id);
919 rot.rotateZ(phi * CLHEP::deg);
920 arm.rotateZ(phi * CLHEP::deg);
921 }
922
923 }
924
925
926
927 for (const auto& rib5 : geo.getRib5s()) {
928
929 const int id = rib5.getId();
930 const double dr = rib5.getDr();
931 const double dz = rib5.getDz();
932 const double width = rib5.getWidth();
933 const double thick = rib5.getThick();
934 const double rin = rib5.getRin();
935 const double x = rib5.getX();
936 const double y = rib5.getY();
937 const double z = rib5.getZ();
938 const double rotx = rib5.getRotx();
939 const double roty = rib5.getRoty();
940 const double rotz = rib5.getRotz();
941 const int offset = rib5.getOffset();
942 const int ndiv = rib5.getNDiv();
943
944 const string solidName = "solidRib5" + to_string(id);
945 const string logicalName = "logicalRib5" + to_string(id);
946
947 const double rmax = rin + thick;
948 const double rmin = rin;
949 const double dphi = 2. * atan2(dz, dr);
950 const double ddphi = thick * tan(dphi) / rin;
951 const double ddphi2 = width / 2. * width / 2. / (x + dr) / rin;
952 const double cphi = dphi - ddphi - ddphi2;
953 G4Tubs* tubeShape = new G4Tubs(solidName,
954 rmin * CLHEP::cm,
955 rmax * CLHEP::cm,
956 0.5 * width * CLHEP::cm,
957 0.,
958 cphi);
959
960 G4LogicalVolume* logicalV = new G4LogicalVolume(tubeShape, medAluminum, logicalName, 0, 0, 0);
961
962 logicalV->SetVisAttributes(m_VisAttributes.back());
963
964 const double phi = 360.0 / ndiv;
965
966 G4RotationMatrix rot = G4RotationMatrix();
967
968
969 G4ThreeVector arm(x * CLHEP::cm, y * CLHEP::cm, z * CLHEP::cm - rin * CLHEP::cm - thick * CLHEP::cm);
970 rot.rotateX(rotx);
971 rot.rotateY(roty);
972 rot.rotateZ(rotz);
973 if (offset) {
974 rot.rotateZ(0.5 * phi * CLHEP::deg);
975 arm.rotateZ(0.5 * phi * CLHEP::deg);
976 }
977 for (int i = 0; i < ndiv; ++i) {
978 const string physicalName = "physicalRib5_" + to_string(id) + " " + to_string(i);
979 new G4PVPlacement(G4Transform3D(rot, arm), logicalV,
980 physicalName.c_str(), m_logicalCDC, false, id);
981 rot.rotateZ(phi * CLHEP::deg);
982 arm.rotateZ(phi * CLHEP::deg);
983 }
984
985 }
986
987
988 createMapper(topVolume);
989 }
DataType Z() const
access variable Z (= .at(2) without boundary check)
B2Vector3< double > B2Vector3D
typedef for common usage with double