18#include "BDSMagnetOuterFactoryPolesBase.hh"
20#include "BDSBeamPipe.hh"
21#include "BDSColours.hh"
23#include "BDSException.hh"
24#include "BDSExtent.hh"
25#include "BDSSimpleComponent.hh"
26#include "BDSGlobalConstants.hh"
27#include "BDSMagnetOuter.hh"
28#include "BDSMagnetOuterFactoryCylindrical.hh"
29#include "BDSMagnetOuterInfo.hh"
30#include "BDSMaterials.hh"
31#include "BDSSDType.hh"
32#include "BDSUtilities.hh"
37#include "G4CutTubs.hh"
38#include "G4ExtrudedSolid.hh"
39#include "G4LogicalVolume.hh"
40#include "G4IntersectionSolid.hh"
41#include "G4Material.hh"
42#include "G4PVPlacement.hh"
43#include "G4SubtractionSolid.hh"
44#include "G4ThreeVector.hh"
46#include "G4TwoVector.hh"
47#include "G4VisAttributes.hh"
57BDSMagnetOuterFactoryPolesBase::BDSMagnetOuterFactoryPolesBase():
64BDSMagnetOuterFactoryPolesBase::~BDSMagnetOuterFactoryPolesBase()
69BDSMagnetOuterFactoryPolesBase::BDSMagnetOuterFactoryPolesBase(G4double poleStopFactorIn):
71 poleAngularFraction(0.7),
73 poleAnnulusFraction(0.1),
74 bendHeightFraction(0.7),
75 poleStopFactor(poleStopFactorIn)
125 G4double containerLength,
129 {
return CreateDipoleH(name, length, beamPipe, containerLength, recipe,
false);}
131 {
return CreateDipoleC(name, length, beamPipe, containerLength, recipe,
false);}
137 G4double containerLength,
141 {
return CreateDipoleH(name, length, beamPipe, containerLength, recipe,
false);}
143 {
return CreateDipoleC(name, length, beamPipe, containerLength, recipe,
false);}
149 G4double containerLength,
158 G4double containerLength,
167 G4double containerLength,
176 G4double containerLength,
185 G4double containerLength,
194 G4double containerLength,
203 G4double containerLength,
212 G4double containerLength,
221 G4double containerLength,
226 {
return CreateDipoleH(name, length, beamPipe, containerLength, recipe, vertical);}
228 {
return CreateDipoleC(name, length, beamPipe, containerLength, recipe, vertical);}
236 G4double magnetContainerLength,
239 G4double horizontalWidth = recipe->horizontalWidth;
240 G4Material* outerMaterial = recipe->outerMaterial;
243 G4Colour* colour = recipe->colour;
259 CreateMagnetContainerComponent();
268 G4double containerRadius = horizontalWidth +
lengthSafety;
308 if (horizontalWidth*0.5 < bpRadius)
310 std::string msg =
"HorizontalWidth (" + std::to_string(horizontalWidth);
311 msg +=
") must be greater than 2*beampipe radius (";
312 msg += std::to_string(2*bpRadius) +
")";
325 G4int nPoles = 2*order;
330 G4double minimumPoleFraction = 0.05;
359 G4double ellipsoidWidth = 2 * ellipsoidCentreY * std::tan(
poleAngle*0.5);
361 ellipsoidWidth = std::min(ellipsoidWidth, poleLength);
364 G4double fraction = std::min(0.5, (G4double)order/10.0);
375 std::vector<G4TwoVector> points;
381 std::vector<G4double> xEllipse;
382 std::vector<G4double> yEllipse;
383 const G4int numAngPoints = 6;
384 const G4double iterant = CLHEP::halfpi/(G4double)numAngPoints;
385 for (G4double angle = 0; angle < CLHEP::halfpi; angle += iterant)
387 xEllipse.push_back(0.5*ellipsoidWidth*std::sin(angle));
388 yEllipse.push_back(0.5*ellipsoidHeight*std::cos(angle));
392 for (G4int i = 0; i < (G4int)xEllipse.size()-1; i++)
393 {points.emplace_back(xEllipse[i], ellipsoidCentreY-yEllipse[i]);}
401 for (G4int i = (G4int)xEllipse.size()-2; i > 0; i--)
402 {points.emplace_back(-xEllipse[i], ellipsoidCentreY-yEllipse[i]);}
404 G4TwoVector zOffsets(0,0);
406 poleSolid =
new G4ExtrudedSolid(name +
"_pole_raw_solid",
423 G4TwoVector zOffsets(0,0);
426 coilLeftSolid =
new G4ExtrudedSolid(name +
"_coil_left_solid",
451 G4double outerX = 0.9 * lowerY * tan (
segmentAngle*0.5);
455 G4double upperY = 0.95 * std::abs(std::sqrt(std::pow(
yokeStartRadius,2) - std::pow(outerX,2)));
458 G4double dx = outerX - innerX;
462 G4double newXHeight = std::max(dx*0.5, dx - (dx-
coilHeight));
463 outerX = innerX + newXHeight;
465 upperY = 0.95 * std::abs(std::sqrt(std::pow(
yokeStartRadius,2) - std::pow(outerX,2)));
489 for (G4double angle = 0; angle <= CLHEP::halfpi; angle+= CLHEP::halfpi / 8.0)
495 for (G4double angle = 0; angle <= CLHEP::halfpi; angle+= CLHEP::halfpi / 8.0)
506 G4double magnetContainerLength,
507 G4double magnetContainerRadiusIn)
510 yokeSolid =
new G4Tubs(name +
"_yoke_solid",
528 containerSolid =
new G4Tubs(name +
"_outer_container_solid",
546 poleSolid =
new G4IntersectionSolid(name +
"_pole_solid",
553 G4Material* outerMaterial)
566 name +
"_coil_left_lv");
570 name +
"_coil_right_lv");
573 G4VisAttributes* coilVisAttr =
new G4VisAttributes(*coil);
574 coilVisAttr->SetVisibility(
true);
578 allVisAttributes.insert(coilVisAttr);
586 G4double& coilHeightFraction)
588 const G4double lowerLimit = 0.05;
589 const G4double upperLimit = 0.98;
590 std::vector<G4double*> fractions = {&coilWidthFraction, &coilHeightFraction};
591 G4String names[2] = {
"coilWidthFraction",
"coilHeightFraction"};
592 for (G4int i = 0; i < 2; i++)
594 if ((*(fractions[i]) < lowerLimit) && (*(fractions[i]) >= 0))
596 *(fractions[i]) = lowerLimit;
597 G4cout << names[i] <<
" is below lower limit - limiting to " << lowerLimit << G4endl;
599 else if (*(fractions[i]) > upperLimit)
601 *(fractions[i]) = upperLimit;
602 G4cout << names[i] <<
" is above upper limit - limiting to " << upperLimit << G4endl;
613 yokePV =
new G4PVPlacement((G4RotationMatrix *)
nullptr,
621 allPhysicalVolumes.insert(yokePV);
627 G4PVPlacement* aPolePV =
nullptr;
628 for (G4int n = 0; n < 2*order; ++n)
630 G4RotationMatrix* rm =
new G4RotationMatrix();
631 allRotationMatrices.insert(rm);
633 G4String pvName = name +
"_pole_" + std::to_string(n) +
"_pv";
635 aPolePV =
new G4PVPlacement(rm,
643 allPhysicalVolumes.insert(aPolePV);
652 G4PVPlacement* coilLeftPV =
nullptr;
653 G4PVPlacement* coilRightPV =
nullptr;
654 G4PVPlacement* endCoilPV =
nullptr;
655 G4RotationMatrix* endCoilRM =
new G4RotationMatrix();
656 endCoilRM->rotateX(CLHEP::halfpi);
660 for (G4int n = 0; n < 2*order; ++n)
665 G4RotationMatrix* rm =
new G4RotationMatrix();
666 G4RotationMatrix* ecrm =
new G4RotationMatrix(*endCoilRM);
667 allRotationMatrices.insert(rm);
668 G4double rotationAngle = (n+0.5)*
segmentAngle + CLHEP::pi*0.5;
673 ecrm->rotateY(rotationAngle);
675 G4String pvName = name +
"_coil_" + std::to_string(n);
676 coilLeftPV =
new G4PVPlacement(rm,
685 coilRightPV =
new G4PVPlacement(rm,
688 pvName +
"_right_pv",
694 G4ThreeVector placementOffset = G4ThreeVector(endCoilTranslation);
695 placementOffset.rotateZ(rotationAngle);
696 endCoilPV =
new G4PVPlacement(ecrm,
699 name +
"_end_piece_coil_pv",
707 allPhysicalVolumes.insert(coilLeftPV);
708 allPhysicalVolumes.insert(coilRightPV);
727 name +
"_end_container_lv");
730 G4TwoVector zOffsets(0,0);
732 G4VSolid* endPieceCoilSolid =
new G4ExtrudedSolid(name +
"_end_coil_solid",
742 name +
"_end_coil_lv");
745 G4VisAttributes* endPieceCoilVis =
new G4VisAttributes(*(
coilLeftLV->GetVisAttributes()));
774 G4double& horizontalWidth,
775 G4Material*& material,
786 std::string msg =
"Error: Faces of magnet (section) named \"" + name +
"\" will overlap!\n";
787 msg +=
"Length of magnet " + std::to_string(length);
788 msg +=
" mm is too short for the angle of the pole faces: (" + std::to_string(angleIn);
789 msg +=
"," + std::to_string(angleOut) +
").";
797 G4cout << __METHOD_NAME__ <<
"coercing vhRatio to (maximum of) 10 for element " << name << G4endl;
799 else if (vhRatio < 0.1)
802 G4cout << __METHOD_NAME__ <<
"coercing vhRatio to (minimum of) 0.1 for element " << name << G4endl;
807 G4bool buildVertically,
810 G4double horizontalWidth,
813 G4double yokeThicknessFraction,
815 G4double coilWidthFraction,
816 G4double coilHeightFraction,
817 G4double& cShapeOuterEdge,
818 G4double& poleHalfGap,
820 G4double& poleHeight,
822 G4double& yokeHalfHeight,
823 G4double& yokeThickness,
824 G4double& yokeOverHang,
826 G4double& coilHeightIn,
827 G4double& coilToYokeGap,
828 G4double& coilToPoleGap,
830 G4double& containerSLength,
831 G4double& intersectionRadius)
835 G4double vhRatioL = buildVertically ? 1./vhRatio : vhRatio;
837 G4double horizontalSize = buildVertically ? vhRatio * horizontalWidth : horizontalWidth;
840 G4double bpHalfWidth = beamPipe->
GetExtent().MaximumX();
841 G4double bpHalfHeight = beamPipe->
GetExtent().MaximumY();
845 {std::swap(bpHalfWidth, bpHalfHeight);}
850 poleWidth = std::max(poleWidth, horizontalSize*0.36);
852 if (poleWidth > 0.9*horizontalSize)
853 {poleWidth = horizontalSize*0.7;}
858 cShapeOuterEdge = std::max(cShapeOuterEdge, 0.5 * poleWidth);
864 yokeWidth = horizontalSize;
865 G4double yokeHeight = horizontalSize * vhRatioL;
871 const G4double margin = 50*CLHEP::um;
872 G4double yokeWidthLowerLimit = 2 * bpHalfWidth + margin;
873 G4double yokeHeightLowerLimit = 2 * bpHalfHeight + margin;
874 if (yokeWidth <= yokeWidthLowerLimit)
875 {yokeWidth = yokeWidthLowerLimit + margin;}
876 if (yokeHeight <= yokeHeightLowerLimit)
877 {yokeHeight = yokeHeightLowerLimit + margin;}
880 yokeThickness = yokeThicknessFraction * horizontalSize;
891 G4double factor = hStyle ? 2.0 : 1.0;
892 if (factor * yokeThickness > yokeWidth - poleWidth)
895 yokeThickness = (yokeWidth - poleWidth) / factor;
899 if (factor * yokeThickness > yokeWidth - 2 * bpHalfWidth)
902 yokeThickness = (yokeWidth - 2 * bpHalfWidth) / factor;
906 {poleHeight = 0.5 * yokeHeight - yokeThickness - poleHalfGap;}
911 G4double yokeThicknessLimitHorizontal = yokeWidth - yokeWidthLowerLimit - margin*0.5;
912 G4double yokeThicknessLimitVertical = 0.5 * yokeHeight - yokeHeightLowerLimit - margin;
913 G4double yokeThicknessLimit = std::min(yokeThicknessLimitHorizontal, 2*yokeThicknessLimitVertical);
914 if (yokeThickness > yokeThicknessLimit)
915 {yokeThickness = yokeThicknessLimit;}
916 if (yokeThickness < margin)
917 {yokeThickness = margin;}
920 yokeHalfHeight = 0.5 * yokeHeight;
924 if (yokeThickness + poleWidth > horizontalSize - margin)
925 {yokeThickness = horizontalWidth - poleWidth - margin;}
928 {yokeOverHang = 0.5*yokeWidth - yokeThickness - 0.5*poleWidth;}
930 {yokeOverHang = yokeWidth - yokeThickness - poleWidth;}
940 containerSLength = sLength;
942 intersectionRadius = std::hypot(0.5*poleWidth + yokeOverHang, poleHalfGap + poleHeight);
944 if (yokeThickness > 0.05*horizontalSize)
945 {intersectionRadius += 0.8 * std::hypot(yokeThickness, yokeThickness);}
947 {intersectionRadius *= 1.3;}
949 coilWidth = yokeOverHang * coilWidthFraction;
950 coilHeightIn = poleHeight * coilHeightFraction;
951 coilToYokeGap = (poleHeight - coilHeightIn) * 0.5;
956 G4double poleHalfGapIn,
957 G4double coilWidthIn,
958 G4double coilHeightIn,
966 G4ThreeVector coilTLDisp = G4ThreeVector( coilDX, coilDY, 0);
967 G4ThreeVector coilTRDisp = G4ThreeVector(-coilDX, coilDY, 0);
968 G4ThreeVector coilBLDisp = G4ThreeVector( coilDX,-coilDY, 0);
969 G4ThreeVector coilBRDisp = G4ThreeVector(-coilDX,-coilDY, 0);
970 std::vector<G4ThreeVector> coilDisps;
971 coilDisps.push_back(coilTLDisp);
972 coilDisps.push_back(coilTRDisp);
973 coilDisps.push_back(coilBLDisp);
974 coilDisps.push_back(coilBRDisp);
981 G4double containerLength,
983 G4bool buildVertically)
985 G4double horizontalWidth = recipe->horizontalWidth;
986 G4double angleIn = recipe->angleIn;
987 G4double angleOut = recipe->angleOut;
988 G4Material* material = recipe->outerMaterial;
989 G4Colour* colour = recipe->colour;
990 G4bool buildEndPiece = recipe->buildEndPieces;
991 G4double vhRatio = recipe->vhRatio;
992 G4double coilWidthFraction = recipe->coilWidthFraction;
993 G4double coilHeightFraction = recipe->coilHeightFraction;
994 G4bool yokeOnLeft = recipe->yokeOnLeft;
1007 G4double cShapeOuterEdge = 0;
1008 G4double poleHalfGap = 0;
1009 G4double poleWidth = 0;
1010 G4double poleHeight = 0;
1011 G4double yokeWidth = 0;
1012 G4double yokeHalfHeight = 0;
1013 G4double yokeThickness = 0;
1014 G4double yokeOverHang = 0;
1015 G4double coilWidth = 0;
1017 G4double coilToYokeGap = 0;
1018 G4double coilToPoleGap = 0;
1019 G4double sLength = length;
1020 G4double containerSLength = containerLength;
1021 G4double intersectionRadius = 0;
1022 DipoleCalculations(
false, buildVertically, beamPipe, length, horizontalWidth, angleIn,
1023 angleOut, 0.23, vhRatio, coilWidthFraction, coilHeightFraction,
1024 cShapeOuterEdge, poleHalfGap, poleWidth, poleHeight,
1025 yokeWidth, yokeHalfHeight, yokeThickness, yokeOverHang, coilWidth,
1027 sLength, containerSLength, intersectionRadius);
1030 G4double yokeInsideX = -0.5*poleWidth - yokeOverHang;
1033 G4double cDY = (poleHeight -
coilHeight)*0.5;
1036 std::vector<G4ThreeVector> coilDisps;
1037 G4double coilDY = 0;
1046 std::vector<G4TwoVector> yokePoints;
1047 std::vector<G4TwoVector> cPoints;
1048 std::vector<G4TwoVector> mCPoints;
1051 G4double extXPos = 0;
1052 G4double extXNeg = 0;
1053 G4double extYPos = 0;
1054 G4double extYNeg = 0;
1062 const G4double phw = 0.5*poleWidth;
1063 const G4double phg = poleHalfGap;
1064 const G4double yw = yokeWidth;
1065 const G4double yhh = yokeHalfHeight;
1066 yokePoints.emplace_back(phw - lsl, phg + lsl);
1067 yokePoints.emplace_back(phw - lsl, yhh - lsl);
1068 yokePoints.emplace_back(phw + lsl - yw, yhh - lsl);
1069 yokePoints.emplace_back(phw + lsl - yw, -yhh + lsl);
1070 yokePoints.emplace_back(phw - lsl, -yhh + lsl);
1071 yokePoints.emplace_back(phw - lsl, -phg - lsl);
1074 yokePoints.emplace_back(-phw + lsl, -phg - lsl);
1075 yokePoints.emplace_back(-phw + lsl, -yhh + yokeThickness);
1076 yokePoints.emplace_back( yokeInsideX - lsl, -yhh + yokeThickness);
1077 yokePoints.emplace_back( yokeInsideX - lsl, yhh - yokeThickness);
1078 yokePoints.emplace_back(-phw + lsl, yhh - yokeThickness);
1079 yokePoints.emplace_back(-phw + lsl, phg + lsl);
1083 yokePoints.emplace_back(yokeInsideX - lsl, -phg - lsl);
1084 yokePoints.emplace_back(yokeInsideX - lsl, phg + lsl);
1089 {cPoints.emplace_back(phw + lsl, phg);}
1092 cPoints.emplace_back(phw + coilWidth + 2*lsl, phg);
1093 cPoints.emplace_back(phw + coilWidth + 2*lsl, phg +
coilHeight + 2*lsl + cDY);
1094 cPoints.emplace_back(phw + lsl, phg +
coilHeight + 2*lsl + cDY);
1096 cPoints.emplace_back(phw + lsl, yhh + lsl);
1097 cPoints.emplace_back(phw - yw - lsl, yhh + lsl);
1098 cPoints.emplace_back(phw - yw - lsl, -yhh - lsl);
1099 cPoints.emplace_back(phw + lsl, -yhh - lsl);
1102 cPoints.emplace_back(phw + lsl, -phg -
coilHeight - 2*lsl - cDY);
1103 cPoints.emplace_back(phw + coilWidth + 2*lsl, -phg -
coilHeight - 2*lsl - cDY);
1104 cPoints.emplace_back(phw + coilWidth + 2*lsl, -phg);
1107 {cPoints.emplace_back(phw + lsl, -phg);}
1108 cPoints.emplace_back(yokeInsideX, -phg);
1109 cPoints.emplace_back(yokeInsideX, phg);
1114 G4double maxLeft = std::max(phw, cShapeOuterEdge);
1115 mCPoints.emplace_back(maxLeft + lsl, phg - lsl);
1118 mCPoints.emplace_back(phw + coilWidth + 4*lsl, phg - lsl);
1119 mCPoints.emplace_back(phw + coilWidth + 4*lsl, phg +
coilHeight + 3*lsl + cDY);
1120 mCPoints.emplace_back(phw + 2*lsl, phg +
coilHeight + 3*lsl + cDY);
1122 mCPoints.emplace_back(phw + 2*lsl, yhh + 2*lsl);
1123 mCPoints.emplace_back(phw - yw - 2*lsl, yhh + 2*lsl);
1124 mCPoints.emplace_back(phw - yw - 2*lsl, -yhh - 2*lsl);
1125 mCPoints.emplace_back(phw + 2*lsl, -yhh - 2*lsl);
1128 mCPoints.emplace_back(phw + 2*lsl, -phg -
coilHeight - 3*lsl - cDY);
1129 mCPoints.emplace_back(phw + coilWidth + 4*lsl, -phg -
coilHeight - 3*lsl - cDY);
1130 mCPoints.emplace_back(phw + coilWidth + 4*lsl, -phg + lsl);
1132 mCPoints.emplace_back(maxLeft + lsl, -phg + lsl);
1135 extXPos = phw + lsl;
1136 extXNeg = phw - yw - 2*lsl;
1137 extYPos = yhh + lsl;
1138 extYNeg = -(yhh +lsl);
1140 {extXPos += coilWidth + lsl;}
1145 for (
auto& vec : yokePoints)
1146 {vec.setX(vec.x() * -1);}
1148 std::reverse(yokePoints.begin(), yokePoints.end());
1151 for (
auto& vec : cPoints)
1152 {vec.setX(vec.x() * -1);}
1153 std::reverse(cPoints.begin(), cPoints.end());
1156 for (
auto& vec : mCPoints)
1157 {vec.setX(vec.x() * -1);}
1158 std::reverse(mCPoints.begin(), mCPoints.end());
1161 std::swap(extXPos, extXNeg);
1165 if (buildVertically)
1167 for (
auto& point : yokePoints)
1169 for (
auto& point : cPoints)
1171 for (
auto& point : mCPoints)
1174 std::swap(extXPos, extYPos);
1175 std::swap(extXNeg, extYNeg);
1179 -length*0.5, length*0.5);
1180 magContExtent = ext;
1182 G4TwoVector zOffsets(0,0);
1183 G4double zScale = 1;
1184 yokeSolid =
new G4ExtrudedSolid(name +
"_yoke_sq_solid",
1191 containerSolid =
new G4ExtrudedSolid(name +
"_outer_sq_container_solid",
1198 magnetContainerSolid =
new G4ExtrudedSolid(name +
"_sq_container_solid",
1200 containerSLength*0.5,
1206 allSolids.insert(containerSolid);
1207 allSolids.insert(magnetContainerSolid);
1209 return DipoleCommonConstruction(name, horizontalWidth, buildEndPiece, coilWidth, length,
1210 containerLength, sLength, angleIn, angleOut,
1212 coilDisps, buildVertically, ext, 0.5*poleWidth, poleHalfGap,
1213 cDY, coilDY, intersectionRadius);
1219 G4double containerLength,
1221 G4bool buildVertically)
1223 G4double horizontalWidth = recipe->horizontalWidth;
1224 G4double angleIn = recipe->angleIn;
1225 G4double angleOut = recipe->angleOut;
1226 G4Material* material = recipe->outerMaterial;
1227 G4Colour* colour = recipe->colour;
1228 G4bool buildEndPiece = recipe->buildEndPieces;
1229 G4double vhRatio = recipe->vhRatio;
1230 G4double coilWidthFraction = recipe->coilWidthFraction;
1231 G4double coilHeightFraction = recipe->coilHeightFraction;
1244 G4double cShapeOuterEdge = 0;
1245 G4double poleHalfGap = 0;
1246 G4double poleWidth = 0;
1247 G4double poleHeight = 0;
1248 G4double yokeWidth = 0;
1249 G4double yokeHalfHeight = 0;
1250 G4double yokeThickness = 0;
1251 G4double yokeOverHang = 0;
1252 G4double coilWidth = 0;
1254 G4double coilToYokeGap = 0;
1255 G4double coilToPoleGap = 0;
1256 G4double sLength = length;
1257 G4double containerSLength = containerLength;
1258 G4double intersectionRadius = 0;
1259 DipoleCalculations(
true, buildVertically, beamPipe, length, horizontalWidth, angleIn,
1260 angleOut, 0.12, vhRatio, coilWidthFraction, coilHeightFraction,
1261 cShapeOuterEdge, poleHalfGap, poleWidth, poleHeight,
1262 yokeWidth, yokeHalfHeight, yokeThickness, yokeOverHang,
1263 coilWidth,
coilHeight, coilToYokeGap, coilToPoleGap,
1264 sLength, containerSLength, intersectionRadius);
1267 G4double yokeInsideX = 0;
1269 {yokeInsideX = 0.5*poleWidth + yokeOverHang;}
1271 {yokeInsideX = 0.5*yokeWidth - yokeThickness;}
1274 G4double yokeInsideY = 0;
1276 {yokeInsideY = poleHalfGap + poleHeight;}
1278 {yokeInsideY = yokeHalfHeight - yokeThickness;}
1281 G4double cDY = (poleHeight -
coilHeight)*0.5;
1286 std::vector<G4ThreeVector> coilDisps;
1287 G4double coilDY = 0;
1296 std::vector<G4TwoVector> yokePoints;
1297 std::vector<G4TwoVector> cPoints;
1298 std::vector<G4TwoVector> mCPoints;
1301 G4double extXPos = 0;
1302 G4double extXNeg = 0;
1303 G4double extYPos = 0;
1304 G4double extYNeg = 0;
1306 G4VSolid* yokeInnerSolid =
nullptr;
1311 const G4double phw = 0.5*poleWidth;
1312 const G4double phg = poleHalfGap;
1313 yokePoints.emplace_back( phw - lsl, phg + lsl);
1314 yokePoints.emplace_back( phw - lsl, yokeInsideY + lsl);
1315 yokePoints.emplace_back( yokeInsideX + lsl, yokeInsideY + lsl);
1316 yokePoints.emplace_back( yokeInsideX + lsl, -yokeInsideY - lsl);
1317 yokePoints.emplace_back( phw - lsl, -yokeInsideY - lsl);
1318 yokePoints.emplace_back( phw - lsl, -phg - lsl);
1319 yokePoints.emplace_back(-phw + lsl, -phg - lsl);
1320 yokePoints.emplace_back(-phw + lsl, -yokeInsideY - lsl);
1321 yokePoints.emplace_back(-yokeInsideX - lsl, -yokeInsideY - lsl);
1322 yokePoints.emplace_back(-yokeInsideX - lsl, yokeInsideY + lsl);
1323 yokePoints.emplace_back(-phw + lsl, yokeInsideY + lsl);
1324 yokePoints.emplace_back(-phw + lsl, phg + lsl);
1327 if (buildVertically)
1329 for (
auto& point : yokePoints)
1333 G4TwoVector zOffsets(0,0);
1334 G4double zScale = 1;
1335 yokeInnerSolid =
new G4ExtrudedSolid(name +
"_yoke_inner_solid",
1344 G4double yIX = buildVertically ? yokeInsideY : yokeInsideX;
1345 G4double yIY = buildVertically ? yokeInsideX : yokeInsideY;
1346 yokeInnerSolid =
new G4Box(name +
"_yoke_inner_solid",
1354 extXPos = 0.5*yokeWidth + lsl;
1355 extXNeg = -0.5*yokeWidth - lsl;
1356 extYPos = 0.5*yokeWidth + lsl;
1357 extYNeg = -0.5*yokeWidth - lsl;
1359 if (buildVertically)
1361 std::swap(extXPos, extYPos);
1362 std::swap(extXNeg, extYNeg);
1366 -length*0.5, length*0.5);
1367 magContExtent = ext;
1369 G4double yokeOuterX = 0.5*yokeWidth - lsl;
1370 G4double yokeOuterY = yokeHalfHeight - lsl;
1371 G4double yOX = buildVertically ? yokeOuterY : yokeOuterX;
1372 G4double yOY = buildVertically ? yokeOuterX : yokeOuterY;
1373 G4VSolid* yokeOuterSolid =
new G4Box(name +
"_yoke_outer_solid",
1376 sLength * 0.5 - lsl);
1378 yokeSolid =
new G4SubtractionSolid(name +
"_yoke_solid",
1383 G4double containerdx = 0.5 * yokeWidth - yokeThickness - lsl;
1384 G4double containerdy = poleHalfGap;
1385 if (buildVertically)
1386 {std::swap(containerdx, containerdy);}
1389 G4VSolid* containerInnerSolid =
new G4Box(name +
"_container_inner_solid",
1393 G4double cOX = 0.5 * yokeWidth;
1394 G4double cOY = yokeHalfHeight;
1395 if (buildVertically)
1396 {std::swap(cOX, cOY);}
1397 G4VSolid* containerOuterSolid =
new G4Box(name +
"_container_outer_solid",
1402 containerSolid =
new G4SubtractionSolid(name +
"_outer_sq_container_solid",
1403 containerOuterSolid,
1404 containerInnerSolid);
1407 magnetContainerSolid =
new G4Box(name +
"_sq_container_solid",
1410 containerSLength * 0.5);
1413 allSolids.insert(yokeInnerSolid);
1414 allSolids.insert(yokeOuterSolid);
1416 allSolids.insert(containerInnerSolid);
1417 allSolids.insert(containerOuterSolid);
1418 allSolids.insert(containerSolid);
1419 allSolids.insert(magnetContainerSolid);
1421 return DipoleCommonConstruction(name, horizontalWidth, buildEndPiece, coilWidth, length,
1422 containerLength, sLength, angleIn, angleOut,
1424 coilDisps, buildVertically, ext, poleWidth*0.5, poleHalfGap,
1425 cDY, coilDY, intersectionRadius);
1428BDSMagnetOuter* BDSMagnetOuterFactoryPolesBase::DipoleCommonConstruction(
const G4String& name,
1429 G4double horizontalWidth,
1430 G4bool buildEndPiece,
1433 G4double containerLength,
1438 G4Material* material,
1439 std::vector<G4ThreeVector>& coilDisps,
1440 G4bool buildVertically,
1442 G4double poleHalfWidth,
1443 G4double poleHalfGap,
1446 G4double intersectionRadius)
1454 G4VSolid* coilSolid =
nullptr;
1455 std::vector<G4VSolid*> coilsSolids;
1456 std::vector<G4LogicalVolume*> coilLVs;
1457 G4bool individualCoilsSolids =
false;
1460 G4double cx = 0.5 * coilWidth - lsl;
1462 coilSolid =
new G4Box(name +
"_coil_solid",
1465 sLength*0.5 - 2*lsl);
1466 allSolids.insert(coilSolid);
1474 inputFaceNormal = faces.first;
1475 outputFaceNormal = faces.second;
1478 G4VSolid* angledFaces =
new G4CutTubs(name +
"_angled_face_solid",
1488 G4VSolid* angledFacesCont =
new G4CutTubs(name +
"_angled_face_cont_solid",
1498 G4VSolid* angledFacesMagCont =
new G4CutTubs(name +
"_angled_face_mag_cont_solid",
1501 containerLength*0.5,
1508 allSolids.insert(angledFaces);
1509 allSolids.insert(angledFacesCont);
1510 allSolids.insert(angledFacesMagCont);
1513 yokeSolid =
new G4IntersectionSolid(name +
"_yoke_solid",
1517 containerSolid =
new G4IntersectionSolid(name +
"_outer_container_solid",
1521 magnetContainerSolid =
new G4IntersectionSolid(name +
"_container_solid",
1522 magnetContainerSolid,
1523 angledFacesMagCont);
1525 individualCoilsSolids =
true;
1528 for (G4int i = 0; i < 4; i++)
1530 G4VSolid* coilS =
new G4IntersectionSolid(name +
"_pole_solid_" + std::to_string(i),
1533 (G4RotationMatrix *)
nullptr,
1535 coilsSolids.push_back(coilS);
1536 allSolids.insert(coilS);
1544 G4LogicalVolume* coilLV =
nullptr;
1548 G4VisAttributes* coilVis =
new G4VisAttributes(*coil);
1549 coilVis->SetVisibility(
true);
1550 allVisAttributes.insert(coilVis);
1552 if (individualCoilsSolids)
1554 for (G4int i = 0; i < 4; i++)
1556 G4String theName = name +
"_coil_solid_" + std::to_string(i);
1557 G4LogicalVolume* aCoilLV =
new G4LogicalVolume(coilsSolids[i],
1560 aCoilLV->SetVisAttributes(coilVis);
1561 coilLVs.push_back(aCoilLV);
1562 allLogicalVolumes.insert(aCoilLV);
1567 coilLV =
new G4LogicalVolume(coilSolid,
1570 coilLV->SetVisAttributes(coilVis);
1571 allLogicalVolumes.insert(coilLV);
1576 for (
auto& lv : coilLVs)
1590 G4PVPlacement* aCoilPV =
nullptr;
1594 for (G4int i = 0; i < 4; i++)
1596 G4LogicalVolume* volToPlace = coilLV;
1597 G4ThreeVector displacement = G4ThreeVector();
1598 if (individualCoilsSolids)
1599 {volToPlace = coilLVs[i];}
1601 {displacement = coilDisps[i];}
1602 G4String theName = name +
"_coil_" + std::to_string(i) +
"_pv";
1603 if (buildVertically)
1605 G4RotationMatrix* rotVert =
new G4RotationMatrix();
1606 rotVert->rotateZ(CLHEP::halfpi);
1607 displacement.transform(*rotVert);
1610 aCoilPV =
new G4PVPlacement(
nullptr,
1618 allPhysicalVolumes.insert(aCoilPV);
1623 CreateMagnetContainerComponent();
1649 if (individualCoilsSolids)
1651 std::set<G4LogicalVolume*> tempLVs(coilLVs.begin(), coilLVs.end());
1671 std::vector<G4TwoVector> inEPPoints;
1672 std::vector<G4TwoVector> outEPPoints;
1674 G4double inXO = poleHalfWidth - lsl;
1678 G4double increment = CLHEP::halfpi/nSegments;
1679 G4double epWidth = buildVertically ?
coilHeight : coilWidth;
1680 for (G4double t = -CLHEP::pi; t <= -CLHEP::halfpi + 1e-9; t += increment)
1682 G4double x = -inXO + epWidth*std::cos(t);
1683 G4double y = epWidth*std::sin(t);
1684 inEPPoints.emplace_back(x,y);
1687 for (G4double t = -CLHEP::halfpi; t <= 0 + 1e-9; t += increment)
1689 G4double x = inXO + epWidth*std::cos(t);
1690 G4double y = epWidth*std::sin(t);
1691 inEPPoints.emplace_back(x,y);
1699 for (
const auto& point : inEPPoints)
1701 G4double outy = -1*(point.x()*std::tan(-angleOut) + point.y());
1702 outEPPoints.emplace_back(point.x(),outy);
1704 for (
auto& point : inEPPoints)
1705 {point.setY(point.x()*std::tan(-angleIn) + point.y());}
1707 G4TwoVector zOffsets(0,0);
1708 G4double zScale = 1;
1711 G4double epHeight = buildVertically ? coilWidth :
coilHeight;
1712 G4VSolid* endPieceSolidIn =
new G4ExtrudedSolid(name +
"_end_coil_in_solid",
1714 0.5 * epHeight - lsl,
1719 G4VSolid* endPieceSolidOut =
new G4ExtrudedSolid(name +
"_end_coil_out_solid",
1721 0.5 * epHeight - lsl,
1727 std::vector<G4TwoVector> contEPPoints;
1728 const G4double connector = 1*CLHEP::mm;
1729 G4double xmax = poleHalfWidth + epWidth + lsl;
1730 G4double ymax = poleHalfGap + epHeight + cDY + lsl;
1731 G4double yInn = poleHalfGap + cDY - lsl;
1732 contEPPoints.emplace_back(xmax + connector, ymax);
1733 contEPPoints.emplace_back(-xmax, ymax);
1734 contEPPoints.emplace_back(-xmax, yInn);
1735 contEPPoints.emplace_back( xmax, yInn);
1736 contEPPoints.emplace_back( xmax, -yInn);
1737 contEPPoints.emplace_back(-xmax, -yInn);
1738 contEPPoints.emplace_back(-xmax, -ymax);
1739 contEPPoints.emplace_back(xmax + connector, -ymax);
1741 G4double containerIntersectionRadius = std::hypot(ymax, xmax);
1743 if (buildVertically)
1745 for (
auto& point : contEPPoints)
1751 G4double ePInLengthZ = ePInLength;
1754 G4double dzIn = std::tan(std::abs(angleIn)) * horizontalWidth;
1755 ePInLength = std::max(2*ePInLength, 2*dzIn);
1760 -ePInLengthZ*0.5, ePInLengthZ*0.5);
1763 -ePInLengthZ*0.5, ePInLengthZ*0.5);
1765 G4VSolid* ePContSolidIn =
new G4ExtrudedSolid(name +
"_end_coil_in_solid",
1767 0.5*ePInLength + lsl,
1772 G4double ePOutLengthZ = ePOutLength;
1775 G4double dzOut = std::tan(std::abs(angleOut)) * horizontalWidth;
1776 ePOutLength = std::max(2*ePOutLength, 2*dzOut);
1779 G4VSolid* ePContSolidOut =
new G4ExtrudedSolid(name +
"_end_coil_out_solid",
1790 G4ThreeVector inputfaceReversed = inputFaceNormal * -1;
1791 G4VSolid* ePContSolidInAng =
new G4CutTubs(name +
"_angled_face_solid",
1793 containerIntersectionRadius,
1801 ePContSolidIn =
new G4IntersectionSolid(name +
"_end_coil_cont_solid",
1809 G4ThreeVector outputfaceReversed = outputFaceNormal * -1;
1810 G4VSolid* ePContSolidOutAng =
new G4CutTubs(name +
"_angled_face_solid",
1812 containerIntersectionRadius,
1820 ePContSolidOut =
new G4IntersectionSolid(name +
"_end_coil_cont_solid",
1830 G4LogicalVolume* ePInLV =
new G4LogicalVolume(endPieceSolidIn,
1832 name +
"_end_coil_in_lv");
1834 G4LogicalVolume* ePContInLV =
new G4LogicalVolume(ePContSolidIn,
1836 name +
"_end_cont_in_lv");
1838 G4LogicalVolume* ePOutLV =
new G4LogicalVolume(endPieceSolidOut,
1840 name +
"_end_coil_out_lv");
1842 G4LogicalVolume* ePContOutLV =
new G4LogicalVolume(ePContSolidOut,
1844 name +
"_end_cont_out_lv");
1847 G4VisAttributes* coilVisIn =
new G4VisAttributes(*coilColour);
1848 coilVisIn->SetVisibility(
true);
1849 G4VisAttributes* coilVisOut =
new G4VisAttributes(*coilVisIn);
1851 ePInLV->SetVisAttributes(coilVisIn);
1852 ePOutLV->SetVisAttributes(coilVisOut);
1862 G4RotationMatrix* endCoilInRM =
new G4RotationMatrix();
1863 endCoilInRM->rotateX(-CLHEP::halfpi);
1864 if (buildVertically)
1865 {endCoilInRM->rotate(CLHEP::halfpi, G4ThreeVector(0,1,0));}
1866 G4ThreeVector endCoilTranslationInTop(0, coilDY-lsl, 0.5*epWidth);
1867 G4ThreeVector endCoilTranslationInLow(0,-coilDY+lsl, 0.5*epWidth);
1868 G4RotationMatrix* vertRot =
new G4RotationMatrix();
1869 vertRot->rotateZ(CLHEP::halfpi);
1870 if (buildVertically)
1872 endCoilTranslationInTop.transform(*vertRot);
1873 endCoilTranslationInLow.transform(*vertRot);
1877 G4PVPlacement* ePInTopPv =
new G4PVPlacement(endCoilInRM,
1878 endCoilTranslationInTop,
1880 name +
"_end_piece_in_top_pv",
1885 G4PVPlacement* ePInLowPv =
new G4PVPlacement(endCoilInRM,
1886 endCoilTranslationInLow,
1888 name +
"_end_piece_in_low_pv",
1894 G4RotationMatrix* endCoilOutRM =
new G4RotationMatrix(*endCoilInRM);
1896 G4ThreeVector endCoilTranslationOutTop(0, coilDY, -0.5*epWidth);
1897 G4ThreeVector endCoilTranslationOutLow(0,-coilDY, -0.5*epWidth);
1898 if (buildVertically)
1900 endCoilTranslationOutTop.transform(*vertRot);
1901 endCoilTranslationOutLow.transform(*vertRot);
1905 G4PVPlacement* ePOutTopPv =
new G4PVPlacement(endCoilOutRM,
1906 endCoilTranslationOutTop,
1908 name +
"_end_piece_out_top_pv",
1913 G4PVPlacement* ePOutLowPv =
new G4PVPlacement(endCoilOutRM,
1914 endCoilTranslationOutLow,
1916 name +
"_end_piece_out_low_pv",
1923 G4ThreeVector inputFaceNormalR = inputFaceNormal * -1;
1943 G4ThreeVector outputFaceNormalR = outputFaceNormal * -1;
1965 outer->SetEndPieceBefore(endPieceInSC);
1966 outer->SetEndPieceAfter(endPieceOutSC);
A holder class for a piece of beam pipe geometry.
G4double GetContainerRadius() const
If it is circular, we need the radius.
G4Colour * GetColour(G4double red, G4double green, G4double blue, G4double alpha=1)
Get a cached anonymous colour by values.
static BDSColours * Instance()
singleton pattern
General exception with possible name of object and message.
Holder for +- extents in 3 dimensions.
G4bool checkOverlaps
Cache of global constants variable.
G4double lengthSafety
Cache of global constants variable.
G4VisAttributes * containerVisAttr
Cache of global constants variable.
G4double lengthSafetyLarge
Cache of global constants variable.
G4int nSegmentsPerCircle
Cache of global constants variable.
G4UserLimits * defaultUserLimits
Cache of global constants variable.
void SetInnerExtent(const BDSExtent &extIn)
Set extent.
BDSExtent GetExtent() const
Accessor - see member for more info.
void RegisterRotationMatrix(G4RotationMatrix *rotationMatrix)
void RegisterLogicalVolume(G4LogicalVolume *logicalVolume)
void RegisterPhysicalVolume(G4VPhysicalVolume *physicalVolume)
void SetExtent(const BDSExtent &extIn)
Set extent.
void RegisterVisAttributes(G4VisAttributes *visAttribute)
void RegisterSolid(G4VSolid *solid)
void RegisterSensitiveVolume(G4LogicalVolume *sensitiveVolume, BDSSDType sensitivityType)
static BDSGlobalConstants * Instance()
Access method.
virtual BDSMagnetOuter * CreateSolenoid(G4String name, G4double length, BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)=0
solenoid outer volume
virtual void CleanUp()
Empty containers for next use - factories are never deleted so can't rely on scope.
virtual void CreateLogicalVolumes(const G4String &name, G4Colour *colour, G4Material *outerMaterial)
void SetFaceNormals(BDSMagnetOuter *outer)
Copy face normals from members to an instance of outer.
G4VSolid * poleSolid
Solid for an individual pole that will be placed multiple times.
virtual BDSMagnetOuter * CreateMuonSpoiler(G4String name, G4double length, BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)=0
muon spoiler outer volume
virtual void SetUserLimits()
Attach default user limits to all logical volumes.
G4bool sensitiveOuter
Cache of global constants variable.
virtual BDSMagnetOuter * CreateMultipole(G4String name, G4double length, BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)=0
general multipole outer volume - could be any 2N order multipole
G4VSolid * yokeSolid
Solid for outer part that connects all poles.
virtual BDSMagnetOuter * CreateRfCavity(G4String name, G4double length, BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)=0
RF cavity outer volume.
void BuildMagnetContainerSolidStraight(const G4String &name, G4double magnetContainerLength, G4double magnetContainerRadius)
Factory that produces cylindrical magnet geometry.
Factory class for outer volume of magnets. Produces magnets with 2N-poles around the beampipe with a ...
void DipoleCommonPreConstruction(const G4String &name, G4double angleIn, G4double angleOut, G4double length, G4double &horizontalWidth, G4Material *&material, G4double &vhRatio)
virtual void CalculatePoleAndYoke(G4double horizontalWidth, BDSBeamPipe *beamPipe, G4int order)
BDSMagnetOuter * CreateDipoleH(const G4String &name, G4double length, const BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe, G4bool buildVertically)
Routine to construct an H shaped dipole magnet and can optionally be built vertically.
void CleanUpPolesBase()
Non-virtual clean up to be used in constructor.
G4double yokeFinishRadius
Finish radius of yoke geometry from magnet centre - less than horizontalWidth.
G4double segmentAngle
2PI / # of poles - angle per segment allocated for each pole.
virtual void CreateEndPiece(const G4String &name)
virtual void IntersectPoleWithYoke(const G4String &name, G4double length, G4int order)
Chop off the top of the pole to match the appropriate yoke geometry.
G4double endPieceOuterR
Outer radius for end piece container.
std::vector< G4ThreeVector > CalculateCoilDisplacements(G4double poleHalfWidthIn, G4double poleHalfGapIn, G4double coilWidthIn, G4double coilHeightIn, G4double cDY, G4double &coilDY)
virtual BDSMagnetOuter * CreateRectangularBend(G4String name, G4double length, const BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)
rectangular bend outer volume
BDSMagnetOuter * CreateDipoleC(const G4String &name, G4double length, const BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe, G4bool buildVertically)
void DipoleCalculations(G4bool hStyle, G4bool buildVertically, const BDSBeamPipe *beamPipe, G4double length, G4double horizontalWidth, G4double angleIn, G4double angleOut, G4double yokeThicknessFraction, G4double vhRatio, G4double coilWidthFraction, G4double coilHeightFraction, G4double &cShapeOuterEdge, G4double &poleHalfGap, G4double &poleWidth, G4double &poleHeight, G4double &yokeWidth, G4double &yokeHalfHeight, G4double &yokeThickness, G4double &yokeOverHang, G4double &coilWidth, G4double &coilHeightIn, G4double &coilToYokeGap, G4double &coilToPoleGap, G4double &sLength, G4double &containerSLength, G4double &intersectionRadius)
virtual BDSMagnetOuter * CreateMuonSpoiler(G4String name, G4double length, BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)
muon spoiler outer volume
G4VSolid * coilLeftSolid
Left coil solid for one pole built upright along y axis.
virtual void CreateLogicalVolumes(const G4String &name, G4Colour *colour, G4Material *outerMaterial)
const G4double poleFraction
virtual BDSMagnetOuter * CreateDecapole(G4String name, G4double length, BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)
decapole outer volume
BDSSimpleComponent * endPiece
Fully constructed end piece.
virtual void CreateCoilSolids(const G4String &name, G4double length)
Create the coil solids corresponding to the pole solid.
const G4double poleAngularFraction
Fraction of 2pi/Npoles that the pole will occupy - always < 1.
G4VSolid * poleIntersectionSolid
Solid used to chop off pole.
G4VSolid * coilRightSolid
Right coil solid.
G4double poleSquareStartRadius
Radius from magnet centre that constant width section starts.
G4LogicalVolume * endPieceCoilLV
Logical volume for end piece single coil piece.
virtual BDSMagnetOuter * CreateSextupole(G4String name, G4double length, BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)
sextupole outer volume
virtual BDSMagnetOuter * CreateSectorBend(G4String name, G4double length, const BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)
sector bend outer volume
G4double magnetContainerRadius
Radius of the container solid for the outer geometry.
G4double poleAngle
The angle allowed for the pole to occupy - less than segmentAngle.
virtual void CreatePoleSolid(const G4String &name, G4double length, G4int order)
virtual void PlaceComponents(const G4String &name, G4int order)
Place the poles and yoke in the container volume.
G4LogicalVolume * endPieceContainerLV
Logical volume for end piece container.
G4double coilCentreRadius
Radius from magnet centre that the centre of the coils exist at.
G4VSolid * endPieceContainerSolid
End piece container solid.
virtual void PlaceComponentsCoils(const G4String &name, G4int order)
If we're building coils, place two coils for each pole.
virtual void CleanUp()
Empty containers for next use - this class is never deleted so can't rely on scope.
std::vector< G4TwoVector > rightPoints
Vector of 2D points for right coil.
std::vector< G4TwoVector > endPiecePoints
Vector of 2D points for end piece looking from above down z.
void TestCoilFractions(G4double &coilWidthFraction, G4double &coilHeightFraction)
G4double poleFinishRadius
Finish radius of the pole from magnet centre.
BDSMagnetOuterFactoryBase * cylindrical
Default factory to fall back to.
virtual void CreateLogicalVolumesCoil(const G4String &name)
G4double endPieceInnerR
Inner radius for end piece container.
std::vector< G4TwoVector > leftPoints
Vector of 2D points for left coil.
G4double endPieceLength
Length of the coil end piece along what will be curvilinear S.
G4double poleStartRadius
Start radius of the pole from magnet centre.
virtual void CreateCoilPoints()
Create all the points that make up the extruded solid of the pole.
virtual BDSMagnetOuter * CreateSolenoid(G4String name, G4double length, BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)
solenoid outer volume
virtual void CreateYokeAndContainerSolid(const G4String &name, G4double length, G4int order, G4double magnetContainerLength, G4double magnetContainerRadiusIn)
G4LogicalVolume * coilRightLV
Logical volume for right coil.
virtual BDSMagnetOuter * CreateRfCavity(G4String name, G4double length, BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)
RF cavity outer volume.
G4bool buildPole
Whether or not to build poles (and therefore coils).
const G4double poleStopFactor
G4double yokeStartRadius
Start radius of yoke geometry from magnet cetnre.
G4double coilHeight
Height along y for coil for coil beside 1 upgright pole aligned with y axis.
const G4double poleTipFraction
virtual BDSMagnetOuter * CreateQuadrupole(G4String name, G4double length, BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)
quadrupole outer volume
virtual BDSMagnetOuter * CreateMultipole(G4String name, G4double length, BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)
general multipole outer volume - could be any 2N order multipole
G4ThreeVector poleTranslation
Offste of pole for placement from magnet centre.
virtual BDSMagnetOuter * CreateOctupole(G4String name, G4double length, BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe)
octupole outer volume
virtual BDSMagnetOuter * CommonConstructor(const G4String &name, G4double length, BDSBeamPipe *beamPipe, G4int order, G4double magnetContainerLength, const BDSMagnetOuterInfo *recipe)
Common construction tasks to all methods - assemble yoke and poles in container.
G4double poleSquareWidth
Full width of pole in constant width section.
G4LogicalVolume * coilLeftLV
Logical volume for left coil.
virtual BDSMagnetOuter * CreateKicker(G4String name, G4double length, const BDSBeamPipe *beamPipe, G4double containerLength, const BDSMagnetOuterInfo *recipe, G4bool vertical)
horizontal and vertical kicker outer volume
Holder struct of all information required to create the outer geometry of a magnet.
G4bool hStyle
H Style for dipoles. If not, it's assumed C style.
An object for both the returned magnet outer body but also a tight fitting container for the whole ma...
static BDSMaterials * Instance()
Singleton pattern access.
G4Material * GetMaterial(G4String material) const
Get material by name.
A BDSAcceleratorComponent wrapper for BDSGeometryComponent.
G4TwoVector Rotate(const G4TwoVector &vec, const G4double &angle)
Rotate a two vector in polar coordinates by an angle.
G4bool WillIntersect(const G4ThreeVector &incomingNormal, const G4ThreeVector &outgoingNormal, const G4double &zSeparation, const BDSExtent &incomingExtent, const BDSExtent &outgoingExtent)
G4double CalculateSafeAngledVolumeLength(G4double angleIn, G4double angleOut, G4double length, G4double containerWidth, G4double containerHeight=0)
Calculate safe length of an angled volume so it fills the length of its container.
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())
std::pair< G4ThreeVector, G4ThreeVector > CalculateFaces(G4double angleInIn, G4double angleOutIn)
Calculate input and output normal vector.