11 #include <vxd/geometry/GeoHeavyMetalShieldCreator.h>
13 #include <geometry/Materials.h>
14 #include <geometry/CreatorFactory.h>
15 #include <geometry/utilities.h>
16 #include <framework/gearbox/GearDir.h>
17 #include <framework/gearbox/Unit.h>
18 #include <framework/logging/Logger.h>
21 #include <boost/format.hpp>
22 #include <boost/algorithm/string.hpp>
23 #include <boost/math/special_functions/sign.hpp>
25 #include <G4LogicalVolume.hh>
26 #include <G4PVPlacement.hh>
27 #include <G4AssemblyVolume.hh>
31 #include <G4Polycone.hh>
32 #include <G4SubtractionSolid.hh>
35 using namespace boost;
43 using namespace geometry;
55 for (
const GearDir& shield : param.getNodes(
"Shield")) {
57 shield.getString(
"@name"),
58 shield.getString(
"Material",
"Air"),
59 shield.getAngle(
"minPhi", 0),
60 shield.getAngle(
"maxPhi", 2 * M_PI),
61 (shield.getNodes(
"Cutout").size() > 0),
62 shield.getLength(
"Cutout/width", 0.),
63 shield.getLength(
"Cutout/height", 0.),
64 shield.getLength(
"Cutout/depth", 0.)
67 for (
const GearDir& plane : shield.getNodes(
"Plane")) {
69 plane.getLength(
"posZ"),
70 plane.getLength(
"innerRadius"),
71 plane.getLength(
"outerRadius")
73 shieldPar.
getPlanes().push_back(planePar);
76 heavyMetalShieldGeometryPar.
getShields().push_back(shieldPar);
78 return heavyMetalShieldGeometryPar;
88 string name = shield.getName();
89 double minZ(0), maxZ(0);
92 double minPhi = shield.getMinPhi();
93 double dPhi = shield.getMaxPhi() - minPhi;
94 int nPlanes = shield.getPlanes().size();
96 B2ERROR(
"Polycone needs at least two planes");
99 std::vector<double> z(nPlanes, 0);
100 std::vector<double> rMin(nPlanes, 0);
101 std::vector<double> rMax(nPlanes, 0);
103 minZ = numeric_limits<double>::infinity();
104 maxZ = -numeric_limits<double>::infinity();
108 z[index] = plane.getPosZ() / Unit::mm;
109 minZ = min(minZ, z[index]);
110 maxZ = max(maxZ, z[index]);
111 rMin[index] = plane.getInnerRadius() / Unit::mm;
112 rMax[index] = plane.getOuterRadius() / Unit::mm;
116 G4VSolid* geoShield =
new G4Polycone(name +
" IR Shield", minPhi, dPhi, nPlanes, z.data(), rMin.data(), rMax.data());
119 if (shield.getDoCutOut()) {
120 double sizeX = shield.getCutOutWidth() / Unit::mm / 2.;
121 double sizeY = shield.getCutOutHeight() / Unit::mm / 2.;
122 double depth2 = shield.getCutOutDepth() / Unit::mm / 2.;
123 double sizeZ = (maxZ - minZ) / 2.;
124 double sign = math::sign<double>(minZ);
125 double minAbsZ = min(fabs(minZ), fabs(maxZ));
127 G4ThreeVector origin1(0, 0, sign * (minAbsZ + sizeZ));
128 G4ThreeVector origin2(0, 0, sign * (minAbsZ + depth2));
130 G4Box* box1 =
new G4Box(
"Cutout", sizeX, sizeY, sizeZ);
131 G4Box* box2 =
new G4Box(
"Cutout", 100 / Unit::mm, sizeY, depth2);
133 geoShield =
new G4SubtractionSolid(name +
" IR Shield", geoShield, box1, G4Translate3D(origin1));
134 geoShield =
new G4SubtractionSolid(name +
" IR Shield", geoShield, box2, G4Translate3D(origin2));
137 string materialName = shield.getMaterial();
138 G4Material* material = Materials::get(materialName);
139 if (!material) B2FATAL(
"Material '" << materialName <<
"', required by " << name <<
" IR Shield could not be found");
141 G4LogicalVolume* volume =
new G4LogicalVolume(geoShield, material, name +
" IR Shield");
144 new G4PVPlacement(0, G4ThreeVector(0, 0, 0), volume, name +
" IR Shield", &topVolume,
false, 0);