12 #include <svd/geometry/GeoSVDCreator.h>
13 #include <vxd/geometry/GeoCache.h>
14 #include <svd/geometry/SensorInfo.h>
15 #include <svd/simulation/SensitiveDetector.h>
17 #include <simulation/background/BkgSensitiveDetector.h>
19 #include <geometry/Materials.h>
20 #include <geometry/CreatorFactory.h>
21 #include <geometry/utilities.h>
22 #include <framework/gearbox/GearDir.h>
23 #include <framework/gearbox/Unit.h>
24 #include <framework/logging/Logger.h>
27 #include <boost/format.hpp>
29 #include <G4LogicalVolume.hh>
30 #include <G4PVPlacement.hh>
36 #include <G4Polycone.hh>
37 #include <G4UnionSolid.hh>
38 #include <G4SubtractionSolid.hh>
39 #include <G4Region.hh>
42 using namespace boost;
49 using namespace geometry;
54 geometry::CreatorFactory<GeoSVDCreator>
GeoSVDFactory(
"SVDCreator");
56 GeoSVDCreator::~GeoSVDCreator()
58 for (
SensorInfo* sensorInfo : m_SensorInfo)
delete sensorInfo;
75 info->setSensorParams(
95 m_SensorInfo.push_back(info);
102 const double unit_pFcm = 1;
107 sensor.getLength(
"width"),
108 sensor.getLength(
"length"),
109 sensor.getLength(
"height"),
110 sensor.getInt(
"stripsU"),
111 sensor.getInt(
"stripsV"),
112 sensor.getLength(
"width2", 0)
115 info->setSensorParams(
116 sensor.getWithUnit(
"stripEdgeU"),
117 sensor.getWithUnit(
"stripEdgeV"),
118 sensor.getWithUnit(
"DepletionVoltage"),
119 sensor.getWithUnit(
"BiasVoltage"),
120 sensor.getDouble(
"BackplaneCapacitanceU") * unit_pFcm,
121 sensor.getDouble(
"InterstripCapacitanceU") * unit_pFcm,
122 sensor.getDouble(
"CouplingCapacitanceU") * unit_pFcm,
123 sensor.getDouble(
"BackplaneCapacitanceV") * unit_pFcm,
124 sensor.getDouble(
"InterstripCapacitanceV") * unit_pFcm,
125 sensor.getDouble(
"CouplingCapacitanceV") * unit_pFcm,
126 sensor.getWithUnit(
"ADUEquivalentU"),
127 sensor.getWithUnit(
"ADUEquivalentV"),
128 sensor.getWithUnit(
"ElectronicNoiseU"),
129 sensor.getWithUnit(
"ElectronicNoiseV"),
130 sensor.getWithUnit(
"ADUEquivalentSbwU", 0),
131 sensor.getWithUnit(
"ADUEquivalentSbwV", 0),
132 sensor.getWithUnit(
"ElectronicNoiseSbwU", 0),
133 sensor.getWithUnit(
"ElectronicNoiseSbwV", 0)
143 sensorInfo->
setID(sensorID);
156 VXDGlobalPar globals((
float)content.getDouble(
"ElectronTolerance", 100),
157 (
float)content.getDouble(
"MinimumElectrons", 10),
158 content.getLength(
"ActiveStepSize", 0.005),
159 content.getBool(
"ActiveChips",
false),
160 content.getBool(
"SeeNeutrons",
false),
161 content.getBool(
"OnlyPrimaryTrueHits",
false),
162 content.getBool(
"OnlyActiveMaterial",
false),
163 (
float)content.getLength(
"DistanceTolerance", 0.005),
164 content.getString(
"DefaultMaterial",
"Air")
169 GearDir envelopeParams(content,
"Envelope/");
171 envelopeParams.
getString(
"Material",
"Air"),
173 envelopeParams.
getAngle(
"minPhi", 0),
174 envelopeParams.
getAngle(
"maxPhi", 2 * M_PI),
175 (envelopeParams.
getNodes(
"InnerPoints/point").size() > 0)
178 for (
const GearDir point : envelopeParams.
getNodes(
"InnerPoints/point")) {
179 pair<double, double> ZXPoint(point.getLength(
"z"), point.getLength(
"x"));
182 for (
const GearDir point : envelopeParams.
getNodes(
"OuterPoints/point")) {
183 pair<double, double> ZXPoint(point.getLength(
"z"), point.getLength(
"x"));
189 string pathAlign = (boost::format(
"Align[@component='%1%']/") % m_prefix).str();
192 B2WARNING(
"Could not find alignment parameters for component " << m_prefix);
193 return svdGeometryPar;
204 GearDir components(content,
"Components/");
205 for (
const GearDir& paramsSensor : components.getNodes(
"Sensor")) {
206 string sensorTypeID = paramsSensor.getString(
"@type");
209 paramsSensor.getString(
"Color",
""),
210 paramsSensor.getLength(
"width"),
211 paramsSensor.getLength(
"width2", 0),
212 paramsSensor.getLength(
"length"),
213 paramsSensor.getLength(
"height"),
214 paramsSensor.getAngle(
"angle", 0),
215 paramsSensor.getBool(
"@slanted",
false)
218 paramsSensor.getString(
"Material"),
219 paramsSensor.getString(
"Active/Color",
"#f00"),
220 paramsSensor.getLength(
"Active/width"),
221 paramsSensor.getLength(
"Active/width2", 0),
222 paramsSensor.getLength(
"Active/length"),
223 paramsSensor.getLength(
"Active/height")
226 paramsSensor.getLength(
"Active/u"),
227 paramsSensor.getLength(
"Active/v"),
228 paramsSensor.getString(
"Active/w",
"center"),
229 paramsSensor.getLength(
"Active/woffset", 0)
233 sensor.setSensorInfo(svdInfo);
234 sensor.setComponents(getSubComponents(paramsSensor));
240 GearDir support(content,
"Support/");
241 readHalfShellSupport(support, svdGeometryPar);
243 for (
const GearDir& shell : content.getNodes(
"HalfShell")) {
245 string shellName = m_prefix +
"." + shell.getString(
"@name");
246 string pathShell = (boost::format(
"Align[@component='%1%']/") % shellName).str();
249 B2WARNING(
"Could not find alignment parameters for component " << shellName);
250 return svdGeometryPar;
260 VXDHalfShellPar halfShell(shell.getString(
"@name") , shell.getAngle(
"shellAngle", 0));
262 for (
const GearDir& layer : shell.getNodes(
"Layer")) {
263 int layerID = layer.getInt(
"@id");
265 readLadder(layerID, components, svdGeometryPar);
266 readLayerSupport(layerID, support, svdGeometryPar);
267 readLadderSupport(layerID, support, svdGeometryPar);
270 for (
const GearDir& ladder : layer.getNodes(
"Ladder")) {
271 int ladderID = ladder.getInt(
"@id");
272 double phi = ladder.getAngle(
"phi", 0);
273 readLadderComponents(layerID, ladderID, content, svdGeometryPar);
274 halfShell.
addLadder(layerID, ladderID, phi);
281 GearDir radiationDir(content,
"RadiationSensors");
285 radiationDir.
getBool(
"insideEnvelope"),
295 position.getLength(
"radius"),
296 position.getAngle(
"theta")
300 for (
GearDir& sensor : position.getNodes(
"phi")) {
302 diamonds.
addSensor(sensor.getInt(
"@id"), sensor.getAngle());
308 return svdGeometryPar;
314 m_activeStepSize = parameters.getGlobalParams().getActiveStepSize() / Unit::mm;
315 m_activeChips = parameters.getGlobalParams().getActiveChips();
316 m_seeNeutrons = parameters.getGlobalParams().getSeeNeutrons();
317 m_onlyPrimaryTrueHits = parameters.getGlobalParams().getOnlyPrimaryTrueHits();
318 m_distanceTolerance = parameters.getGlobalParams().getDistanceTolerance();
319 m_electronTolerance = parameters.getGlobalParams().getElectronTolerance();
320 m_minimumElectrons = parameters.getGlobalParams().getMinimumElectrons();
321 m_onlyActiveMaterial = parameters.getGlobalParams().getOnlyActiveMaterial();
322 m_defaultMaterial = parameters.getGlobalParams().getDefaultMaterial();
324 G4Material* material = Materials::get(m_defaultMaterial);
325 if (!material) B2FATAL(
"Default Material of VXD, '" << m_defaultMaterial <<
"', could not be found");
329 G4LogicalVolume* envelope(0);
330 G4VPhysicalVolume* physEnvelope{
nullptr};
331 if (!parameters.getEnvelope().getExists()) {
332 B2INFO(
"Could not find definition for " + m_prefix +
" Envelope, placing directly in top volume");
333 envelope = &topVolume;
335 double minZ(0), maxZ(0);
336 G4Polycone* envelopeCone = geometry::createRotationSolid(
"Envelope",
337 parameters.getEnvelope().getInnerPoints(),
338 parameters.getEnvelope().getOuterPoints(),
339 parameters.getEnvelope().getMinPhi(),
340 parameters.getEnvelope().getMaxPhi(),
343 envelope =
new G4LogicalVolume(envelopeCone, material, m_prefix +
".Envelope");
345 physEnvelope =
new G4PVPlacement(getAlignment(parameters.getAlignment(m_prefix)), envelope, m_prefix +
".Envelope",
346 &topVolume,
false, 1);
349 G4Region* aRegion =
new G4Region(
"SVDEnvelope");
350 envelope->SetRegion(aRegion);
351 aRegion->AddRootLogicalVolume(envelope);
355 for (
const pair<const string, VXDGeoSensorPar>& typeAndSensor : parameters.getSensorMap()) {
356 const string& sensorTypeID = typeAndSensor.first;
381 sensor.setSensorInfo(createSensorInfo(paramsSensor));
383 vector<VXDGeoPlacement> subcomponents;
387 component.getU() / Unit::mm,
388 component.getV() / Unit::mm,
390 component.getWOffset() / Unit::mm
393 sensor.setComponents(subcomponents);
394 m_sensorMap[sensorTypeID] = sensor;
398 for (
const string& name : parameters.getComponentInsertOder()) {
399 if (m_componentCache.find(name) != m_componentCache.end()) {
404 B2WARNING(
"Component " << name <<
" already created from previous subcomponents, should not be here");
411 paramsComponent.
getWidth() / Unit::mm,
416 double angle = paramsComponent.
getAngle();
419 if (c.getWidth() <= 0 || c.getLength() <= 0 || c.getHeight() <= 0) {
420 B2DEBUG(100,
"One dimension empty, using auto resize for component");
422 G4VSolid* solid = createTrapezoidal(m_prefix +
"." + name, c.getWidth(), c.getWidth2(), c.getLength(), c.getHeight(), angle);
423 c.setVolume(
new G4LogicalVolume(solid, Materials::get(c.getMaterial()), m_prefix +
"." + name));
426 vector<VXDGeoPlacement> subComponents;
429 paramsSubComponent.getName(),
430 paramsSubComponent.getU() / Unit::mm,
431 paramsSubComponent.getV() / Unit::mm,
432 paramsSubComponent.getW(),
433 paramsSubComponent.getWOffset() / Unit::mm
438 createSubComponents(m_prefix +
"." + name, c, subComponents);
439 if (m_activeChips && parameters.getSensitiveChipID(name) >= 0) {
440 int chipID = parameters.getSensitiveChipID(name);
441 B2DEBUG(50,
"Creating BkgSensitiveDetector for component " << name <<
" with chipID " << chipID);
443 c.getVolume()->SetSensitiveDetector(sensitive);
444 m_sensitive.push_back(sensitive);
447 m_componentCache[name] = c;
455 string shellName = shell.getName();
456 m_currentHalfShell = m_prefix +
"." + shellName;
457 G4Transform3D shellAlignment = getAlignment(parameters.getAlignment(m_currentHalfShell));
460 VXD::GeoCache::getInstance().addHalfShellPlacement(m_halfShellVxdIDs[m_currentHalfShell], shellAlignment);
463 double shellAngle = shell.getShellAngle();
464 if (!m_onlyActiveMaterial) shellSupport.
place(envelope, shellAlignment * G4RotateZ3D(shellAngle));
467 for (
const std::pair<
const int, std::vector<std::pair<int, double>> >& layer : shell.getLayers()) {
468 int layerID = layer.first;
469 const std::vector<std::pair<int, double>>& Ladders = layer.second;
472 setCurrentLayer(layerID, parameters);
476 if (!m_onlyActiveMaterial) layerSupport.
place(envelope, shellAlignment * G4RotateZ3D(shellAngle));
480 for (
const std::pair<int, double>& ladder : Ladders) {
481 int ladderID = ladder.first;
482 double phi = ladder.second;
484 G4Transform3D ladderPlacement = placeLadder(ladderID, phi, envelope, shellAlignment, parameters);
485 if (!m_onlyActiveMaterial) ladderSupport.
place(envelope, ladderPlacement);
493 VXD::GeoCache::getInstance().findVolumes(physEnvelope);
496 G4PVPlacement topPlacement(
nullptr, G4ThreeVector(0, 0, 0), &topVolume,
497 "temp_Top",
nullptr,
false, 1,
false);
499 VXD::GeoCache::getInstance().findVolumes(&topPlacement);
504 if (parameters.getRadiationSensors().getSubDetector() ==
"") {
505 B2DEBUG(10,
"Apparently no radiation sensors defined, skipping");
507 createDiamonds(parameters.getRadiationSensors(), topVolume, *envelope);
514 if (!support)
return;
516 for (
const GearDir& params : support.
getNodes(
"HalfShell/RotationSolid")) {
519 params.getString(
"Material",
"Air"),
520 params.getString(
"Color",
""),
521 params.getAngle(
"minPhi", 0),
522 params.getAngle(
"maxPhi", 2 * M_PI),
523 (params.getNodes(
"InnerPoints/point").size() > 0)
526 for (
const GearDir point : params.getNodes(
"InnerPoints/point")) {
527 pair<double, double> ZXPoint(point.getLength(
"z"), point.getLength(
"x"));
530 for (
const GearDir point : params.getNodes(
"OuterPoints/point")) {
531 pair<double, double> ZXPoint(point.getLength(
"z"), point.getLength(
"x"));
541 if (!support)
return;
544 GearDir endrings(support, (boost::format(
"Endrings/Layer[@id='%1%']") % layer).str());
549 support.
getLength(
"Endrings/baseThickness")
555 endring.getLength(
"z"),
556 endring.getLength(
"baseRadius"),
557 endring.getLength(
"innerRadius"),
558 endring.getLength(
"outerRadius"),
559 endring.getLength(
"horizontalBar"),
560 endring.getLength(
"verticalBar")
562 svdGeometryPar.
getEndrings()[layer].getTypes().push_back(endringPar);
567 GearDir pipes(support, (boost::format(
"CoolingPipes/Layer[@id='%1%']") % layer).str());
570 support.
getLength(
"CoolingPipes/outerDiameter"),
571 support.
getLength(
"CoolingPipes/wallThickness"),
586 if (!support)
return;
589 GearDir params(support, (boost::format(
"SupportRibs/Layer[@id='%1%']") % layer).str());
593 support.
getLength(
"SupportRibs/inner/width"),
594 support.
getLength(
"SupportRibs/outer/width"),
595 support.
getLength(
"SupportRibs/inner/tabLength"),
596 support.
getString(
"SupportRibs/outer/Material"),
597 support.
getString(
"SupportRibs/inner/Material"),
598 support.
getString(
"SupportRibs/outer/Color"),
599 support.
getString(
"SupportRibs/inner/Color"),
600 support.
getString(
"SupportRibs/endmount/Material")
604 if (params.exists(
"spacing")) svdGeometryPar.
getSupportRibs()[layer].setSpacing(params.getLength(
"spacing"));
605 if (params.exists(
"height")) svdGeometryPar.
getSupportRibs()[layer].setHeight(params.getLength(
"height"));
607 for (
const GearDir& box : params.getNodes(
"box")) {
611 box.getLength(
"length")
613 svdGeometryPar.
getSupportRibs()[layer].getBoxes().push_back(boxPar);
616 for (
const GearDir& tab : params.getNodes(
"tab")) {
621 svdGeometryPar.
getSupportRibs()[layer].getTabs().push_back(tabPar);
624 for (
const GearDir& endmount : params.getNodes(
"Endmount")) {
626 endmount.getLength(
"height"),
627 endmount.getLength(
"width"),
628 endmount.getLength(
"length"),
629 endmount.getLength(
"z"),
630 endmount.getLength(
"r")
632 svdGeometryPar.
getSupportRibs()[layer].getEndmounts().push_back(mountPar);
643 double minZ(0), maxZ(0);
645 const std::vector<VXDRotationSolidPar>& RotationSolids = parameters.getRotationSolids();
649 string name = component.getName();
650 string material = component.getMaterial();
652 G4Polycone* solid = geometry::createRotationSolid(name,
653 component.getInnerPoints(),
654 component.getOuterPoints(),
655 component.getMinPhi(),
656 component.getMaxPhi(),
660 G4LogicalVolume* volume =
new G4LogicalVolume(
661 solid, geometry::Materials::get(material), m_prefix +
". " + name);
662 geometry::setColor(*volume, component.getColor());
663 supportAssembly.
add(volume);
665 return supportAssembly;
675 if (parameters.getEndringsExist(layer)) {
679 double length = support.
getLength() / Unit::mm / 2.0;
680 double gapWidth = support.
getGapWidth() / Unit::mm;
684 const std::vector<SVDEndringsTypePar>& Endrings = support.
getTypes();
686 double z = endring.getZ() / Unit::mm;
687 double baseRadius = endring.getBaseRadius() / Unit::mm;
688 double innerRadius = endring.getInnerRadius() / Unit::mm;
689 double outerRadius = endring.getOuterRadius() / Unit::mm;
690 double horiBarWidth = endring.getHorizontalBarWidth() / Unit::mm / 2.0;
691 double vertBarWidth = endring.getVerticalBarWidth() / Unit::mm / 2.0;
693 double angle = asin(gapWidth / innerRadius);
694 G4VSolid* endringSolid =
new G4Tubs(
"OuterEndring", innerRadius, outerRadius, length, -M_PI / 2 + angle, M_PI - 2 * angle);
695 angle = asin(gapWidth / baseRadius);
696 G4VSolid* endringBase =
new G4Tubs(
"InnerEndring", baseRadius, baseRadius + baseThickness, length, -M_PI / 2 + angle,
698 endringSolid =
new G4UnionSolid(
"Endring", endringSolid, endringBase);
701 double height = (innerRadius - baseRadius) / 2.0;
702 double x = vertBarWidth + gapWidth;
703 G4Box* verticalBar =
new G4Box(
"VerticalBar", vertBarWidth, height, length);
704 G4Box* horizontalBar =
new G4Box(
"HorizontalBar", height, horiBarWidth, length);
705 endringSolid =
new G4UnionSolid(
"Endring", endringSolid, verticalBar, G4Translate3D(x, baseRadius + height, 0));
706 endringSolid =
new G4UnionSolid(
"Endring", endringSolid, verticalBar, G4Translate3D(x, -(baseRadius + height), 0));
707 endringSolid =
new G4UnionSolid(
"Endring", endringSolid, horizontalBar, G4Translate3D((baseRadius + height), 0, 0));
710 G4LogicalVolume* endringVolume =
new G4LogicalVolume(
711 endringSolid, geometry::Materials::get(material),
712 (boost::format(
"%1%.Layer%2%.%3%") % m_prefix % layer % endring.getName()).str());
713 supportAssembly.
add(endringVolume, G4TranslateZ3D(z));
718 if (parameters.getCoolingPipesExist(layer)) {
727 double radius = pipes.
getRadius() / Unit::mm;
728 double zstart = pipes.
getZStart() / Unit::mm;
729 double zend = pipes.
getZEnd() / Unit::mm;
730 double zlength = (zend - zstart) / 2.0;
735 G4Tubs* pipeSolid =
new G4Tubs(
"CoolingPipe", innerRadius, outerRadius, zlength, 0, 2 * M_PI);
736 G4LogicalVolume* pipeVolume =
new G4LogicalVolume(
737 pipeSolid, geometry::Materials::get(material),
738 (boost::format(
"%1%.Layer%2%.CoolingPipe") % m_prefix % layer).str());
739 geometry::setColor(*pipeVolume,
"#ccc");
741 G4Torus* bendSolid =
new G4Torus(
"CoolingBend", innerRadius, outerRadius, sin(deltaPhi / 2.0)*radius, -M_PI / 2, M_PI);
742 G4LogicalVolume* bendVolume =
new G4LogicalVolume(
743 bendSolid, geometry::Materials::get(material),
744 (boost::format(
"%1%.Layer%2%.CoolingBend") % m_prefix % layer).str());
748 double deltaL = pipes.
getDeltaL() / Unit::mm;
749 G4Torus* bendSolidLast =
new G4Torus(
"CoolingBendLast", innerRadius, outerRadius, sin(deltaPhi / 2.0) * radius - deltaL / 2.0,
751 G4LogicalVolume* bendVolumeLast =
new G4LogicalVolume(bendSolidLast, geometry::Materials::get(material),
752 (boost::format(
"%1%.Layer%2%.CoolingBendLast") % m_prefix % layer).str());
756 G4Transform3D placement_pipe = G4RotateZ3D(startPhi + (nPipes - 0.5) * deltaPhi) * G4Translate3D(cos(deltaPhi / 2.0) * radius,
757 sin(deltaPhi / 2.0) * radius - deltaL, zstart + zlength);
758 supportAssembly.
add(pipeVolume, placement_pipe);
761 double zpos = nPipes % 2 > 0 ? zend : zstart;
763 G4Transform3D placement = G4RotateZ3D(startPhi + (nPipes - 0.5) * deltaPhi) * G4Translate3D(cos(deltaPhi / 2.0) * radius,
764 -deltaL / 2.0, zpos) * G4RotateY3D(M_PI / 2);
766 if (nPipes % 2 > 0) {
767 placement = placement * G4RotateZ3D(M_PI);
770 supportAssembly.
add(bendVolumeLast, placement);
773 for (
int i = 0; i < nPipes; ++i) {
775 G4Transform3D placement_pipe = G4RotateZ3D(startPhi + i * deltaPhi) * G4Translate3D(radius, 0, zstart + zlength);
776 supportAssembly.
add(pipeVolume, placement_pipe);
781 double zpos = i % 2 > 0 ? zend : zstart;
783 G4Transform3D placement = G4RotateZ3D(startPhi + (i - 0.5) * deltaPhi) * G4Translate3D(cos(deltaPhi / 2.0) * radius, 0,
784 zpos) * G4RotateY3D(M_PI / 2);
787 placement = placement * G4RotateZ3D(M_PI);
790 supportAssembly.
add(bendVolume, placement);
795 return supportAssembly;
804 if (!parameters.getSupportRibsExist(layer))
return supportAssembly;
808 double spacing = support.
getSpacing() / Unit::mm / 2.0;
809 double height = support.
getHeight() / Unit::mm / 2.0;
810 double innerWidth = support.
getInnerWidth() / Unit::mm / 2.0;
811 double outerWidth = support.
getOuterWidth() / Unit::mm / 2.0;
812 double tabLength = support.
getTabLength() / Unit::mm / 2.0;
815 G4Transform3D placement;
819 const std::vector<SVDSupportBoxPar>& Boxes = support.
getBoxes();
821 double theta = box.getTheta();
822 double zpos = box.getZ() / Unit::mm;
823 double rpos = box.getR() / Unit::mm;
824 double length = box.getLength() / Unit::mm / 2.0;
825 G4Box* innerBox =
new G4Box(
"innerBox", height, innerWidth, length);
826 G4Box* outerBox =
new G4Box(
"outerBox", height, outerWidth, length);
830 placement = G4Translate3D(rpos, 0, zpos) * G4RotateY3D(theta);
832 G4Transform3D relative = placement.inverse() * G4Translate3D(rpos, 0, zpos) * G4RotateY3D(theta);
833 inner =
new G4UnionSolid(
"innerBox", inner, innerBox, relative);
834 outer =
new G4UnionSolid(
"outerBox", outer, outerBox, relative);
839 const std::vector<SVDSupportTabPar>& Tabs = support.
getTabs();
841 double theta = tab.getTheta();
842 double zpos = tab.getZ() / Unit::mm;
843 double rpos = tab.getR() / Unit::mm;
844 G4Box* innerBox =
new G4Box(
"innerBox", height, innerWidth, tabLength);
847 placement = G4Translate3D(rpos, 0, zpos) * G4RotateY3D(theta);
849 G4Transform3D relative = placement.inverse() * G4Translate3D(rpos, 0, zpos) * G4RotateY3D(theta);
850 inner =
new G4UnionSolid(
"innerBox", inner, innerBox, relative);
855 const std::vector<SVDEndmountPar>& Endmounts = support.
getEndmounts();
857 double endMountHeight = endmount.getHeight() / Unit::mm / 2.0;
858 double endMountWidth = endmount.getWidth() / Unit::mm / 2.0;
859 double endMountLength = endmount.getLength() / Unit::mm / 2.0;
860 double zpos = endmount.getZ() / Unit::mm;
861 double rpos = endmount.getR() / Unit::mm;
862 G4VSolid* endmountBox =
new G4Box(
"endmountBox", endMountHeight, endMountWidth, endMountLength);
864 endmountBox =
new G4SubtractionSolid(
"endmountBox", endmountBox, outer, G4TranslateY3D(-spacing)*placement * G4Translate3D(-rpos, 0,
866 endmountBox =
new G4SubtractionSolid(
"endmountBox", endmountBox, outer, G4TranslateY3D(spacing)*placement * G4Translate3D(-rpos, 0,
869 G4LogicalVolume* endmountVolume =
new G4LogicalVolume(
871 (boost::format(
"%1%.Layer%2%.%3%Endmount") % m_prefix % layer % endmount.getName()).str());
872 supportAssembly.
add(endmountVolume, G4Translate3D(rpos, 0, zpos));
877 outer =
new G4SubtractionSolid(
"outerBox", outer, inner);
878 G4LogicalVolume* outerVolume =
new G4LogicalVolume(
880 (boost::format(
"%1%.Layer%2%.SupportRib") % m_prefix % layer).str());
881 G4LogicalVolume* innerVolume =
new G4LogicalVolume(
883 (boost::format(
"%1%.Layer%2%.SupportRib.Airex") % m_prefix % layer).str());
886 supportAssembly.
add(innerVolume, G4TranslateY3D(-spacing)*placement);
887 supportAssembly.
add(innerVolume, G4TranslateY3D(spacing)*placement);
888 supportAssembly.
add(outerVolume, G4TranslateY3D(-spacing)*placement);
889 supportAssembly.
add(outerVolume, G4TranslateY3D(spacing)*placement);
893 return supportAssembly;