19#include "BDSMagnetOuterFactoryPolesBase.hh"
21#include "BDSBeamPipe.hh"
22#include "BDSColours.hh"
24#include "BDSException.hh"
25#include "BDSExtent.hh"
26#include "BDSSimpleComponent.hh"
27#include "BDSGlobalConstants.hh"
28#include "BDSMagnetOuter.hh"
29#include "BDSMagnetOuterFactoryCylindrical.hh"
30#include "BDSMagnetOuterInfo.hh"
31#include "BDSMaterials.hh"
32#include "BDSSDType.hh"
33#include "BDSUtilities.hh"
38#include "G4CutTubs.hh"
39#include "G4ExtrudedSolid.hh"
40#include "G4LogicalVolume.hh"
41#include "G4IntersectionSolid.hh"
42#include "G4Material.hh"
43#include "G4PVPlacement.hh"
44#include "G4SubtractionSolid.hh"
45#include "G4ThreeVector.hh"
47#include "G4TwoVector.hh"
48#include "G4VisAttributes.hh"
58BDSMagnetOuterFactoryPolesBase::BDSMagnetOuterFactoryPolesBase():
65BDSMagnetOuterFactoryPolesBase::~BDSMagnetOuterFactoryPolesBase()
70BDSMagnetOuterFactoryPolesBase::BDSMagnetOuterFactoryPolesBase(G4double poleStopFactorIn):
72 poleAngularFraction(0.7),
74 poleAnnulusFraction(0.1),
75 bendHeightFraction(0.7),
76 poleStopFactor(poleStopFactorIn)
126 G4double containerLength,
130 {
return CreateDipoleH(name, length, beamPipe, containerLength, recipe,
false);}
132 {
return CreateDipoleC(name, length, beamPipe, containerLength, recipe,
false);}
138 G4double containerLength,
142 {
return CreateDipoleH(name, length, beamPipe, containerLength, recipe,
false);}
144 {
return CreateDipoleC(name, length, beamPipe, containerLength, recipe,
false);}
150 G4double containerLength,
159 G4double containerLength,
168 G4double containerLength,
177 G4double containerLength,
186 G4double containerLength,
195 G4double containerLength,
204 G4double containerLength,
213 G4double containerLength,
222 G4double containerLength,
227 {
return CreateDipoleH(name, length, beamPipe, containerLength, recipe, vertical);}
229 {
return CreateDipoleC(name, length, beamPipe, containerLength, recipe, vertical);}
237 G4double magnetContainerLength,
240 G4double horizontalWidth = recipe->horizontalWidth;
241 G4Material* outerMaterial = recipe->outerMaterial;
244 G4Colour* colour = recipe->colour;
260 CreateMagnetContainerComponent();
269 G4double containerRadius = horizontalWidth +
lengthSafety;
309 if (horizontalWidth*0.5 < bpRadius)
311 std::string msg =
"HorizontalWidth (" + std::to_string(horizontalWidth);
312 msg +=
") must be greater than 2*beampipe radius (";
313 msg += std::to_string(2*bpRadius) +
")";
326 G4int nPoles = 2*order;
331 G4double minimumPoleFraction = 0.05;
360 G4double ellipsoidWidth = 2 * ellipsoidCentreY * std::tan(
poleAngle*0.5);
362 ellipsoidWidth = std::min(ellipsoidWidth, poleLength);
365 G4double fraction = std::min(0.5, (G4double)order/10.0);
376 std::vector<G4TwoVector> points;
382 std::vector<G4double> xEllipse;
383 std::vector<G4double> yEllipse;
384 const G4int numAngPoints = 6;
385 const G4double iterant = CLHEP::halfpi/(G4double)numAngPoints;
386 for (G4double angle = 0; angle < CLHEP::halfpi; angle += iterant)
388 xEllipse.push_back(0.5*ellipsoidWidth*std::sin(angle));
389 yEllipse.push_back(0.5*ellipsoidHeight*std::cos(angle));
393 for (G4int i = 0; i < (G4int)xEllipse.size()-1; i++)
394 {points.emplace_back(xEllipse[i], ellipsoidCentreY-yEllipse[i]);}
402 for (G4int i = (G4int)xEllipse.size()-2; i > 0; i--)
403 {points.emplace_back(-xEllipse[i], ellipsoidCentreY-yEllipse[i]);}
405 G4TwoVector zOffsets(0,0);
407 poleSolid =
new G4ExtrudedSolid(name +
"_pole_raw_solid",
424 G4TwoVector zOffsets(0,0);
427 coilLeftSolid =
new G4ExtrudedSolid(name +
"_coil_left_solid",
452 G4double outerX = 0.9 * lowerY * tan (
segmentAngle*0.5);
456 G4double upperY = 0.95 * std::abs(std::sqrt(std::pow(
yokeStartRadius,2) - std::pow(outerX,2)));
459 G4double dx = outerX - innerX;
463 G4double newXHeight = std::max(dx*0.5, dx - (dx-
coilHeight));
464 outerX = innerX + newXHeight;
466 upperY = 0.95 * std::abs(std::sqrt(std::pow(
yokeStartRadius,2) - std::pow(outerX,2)));
490 for (G4double angle = 0; angle <= CLHEP::halfpi; angle+= CLHEP::halfpi / 8.0)
496 for (G4double angle = 0; angle <= CLHEP::halfpi; angle+= CLHEP::halfpi / 8.0)
507 G4double magnetContainerLength,
508 G4double magnetContainerRadiusIn)
511 yokeSolid =
new G4Tubs(name +
"_yoke_solid",
529 containerSolid =
new G4Tubs(name +
"_outer_container_solid",
547 poleSolid =
new G4IntersectionSolid(name +
"_pole_solid",
554 G4Material* outerMaterial)
567 name +
"_coil_left_lv");
571 name +
"_coil_right_lv");
574 G4VisAttributes* coilVisAttr =
new G4VisAttributes(*coil);
575 coilVisAttr->SetVisibility(
true);
579 allVisAttributes.insert(coilVisAttr);
587 G4double& coilHeightFraction)
589 const G4double lowerLimit = 0.05;
590 const G4double upperLimit = 0.98;
591 std::vector<G4double*> fractions = {&coilWidthFraction, &coilHeightFraction};
592 G4String names[2] = {
"coilWidthFraction",
"coilHeightFraction"};
593 for (G4int i = 0; i < 2; i++)
595 if ((*(fractions[i]) < lowerLimit) && (*(fractions[i]) >= 0))
597 *(fractions[i]) = lowerLimit;
598 G4cout << names[i] <<
" is below lower limit - limiting to " << lowerLimit << G4endl;
600 else if (*(fractions[i]) > upperLimit)
602 *(fractions[i]) = upperLimit;
603 G4cout << names[i] <<
" is above upper limit - limiting to " << upperLimit << G4endl;
614 yokePV =
new G4PVPlacement((G4RotationMatrix *)
nullptr,
622 allPhysicalVolumes.insert(yokePV);
628 G4PVPlacement* aPolePV =
nullptr;
629 for (G4int n = 0; n < 2*order; ++n)
631 G4RotationMatrix* rm =
new G4RotationMatrix();
632 allRotationMatrices.insert(rm);
634 G4String pvName = name +
"_pole_" + std::to_string(n) +
"_pv";
636 aPolePV =
new G4PVPlacement(rm,
644 allPhysicalVolumes.insert(aPolePV);
653 G4PVPlacement* coilLeftPV =
nullptr;
654 G4PVPlacement* coilRightPV =
nullptr;
655 G4PVPlacement* endCoilPV =
nullptr;
656 G4RotationMatrix* endCoilRM =
new G4RotationMatrix();
657 endCoilRM->rotateX(CLHEP::halfpi);
661 for (G4int n = 0; n < 2*order; ++n)
666 G4RotationMatrix* rm =
new G4RotationMatrix();
667 G4RotationMatrix* ecrm =
new G4RotationMatrix(*endCoilRM);
668 allRotationMatrices.insert(rm);
669 G4double rotationAngle = (n+0.5)*
segmentAngle + CLHEP::pi*0.5;
674 ecrm->rotateY(rotationAngle);
676 G4String pvName = name +
"_coil_" + std::to_string(n);
677 coilLeftPV =
new G4PVPlacement(rm,
686 coilRightPV =
new G4PVPlacement(rm,
689 pvName +
"_right_pv",
695 G4ThreeVector placementOffset = G4ThreeVector(endCoilTranslation);
696 placementOffset.rotateZ(rotationAngle);
697 endCoilPV =
new G4PVPlacement(ecrm,
700 name +
"_end_piece_coil_pv",
708 allPhysicalVolumes.insert(coilLeftPV);
709 allPhysicalVolumes.insert(coilRightPV);
728 name +
"_end_container_lv");
731 G4TwoVector zOffsets(0,0);
733 G4VSolid* endPieceCoilSolid =
new G4ExtrudedSolid(name +
"_end_coil_solid",
743 name +
"_end_coil_lv");
746 G4VisAttributes* endPieceCoilVis =
new G4VisAttributes(*(
coilLeftLV->GetVisAttributes()));
775 G4double& horizontalWidth,
776 G4Material*& material,
787 std::string msg =
"Error: Faces of magnet (section) named \"" + name +
"\" will overlap!\n";
788 msg +=
"Length of magnet " + std::to_string(length);
789 msg +=
" mm is too short for the angle of the pole faces: (" + std::to_string(angleIn);
790 msg +=
"," + std::to_string(angleOut) +
").";
798 G4cout << __METHOD_NAME__ <<
"coercing vhRatio to (maximum of) 10 for element " << name << G4endl;
800 else if (vhRatio < 0.1)
803 G4cout << __METHOD_NAME__ <<
"coercing vhRatio to (minimum of) 0.1 for element " << name << G4endl;
808 G4bool buildVertically,
811 G4double horizontalWidth,
814 G4double yokeThicknessFraction,
816 G4double coilWidthFraction,
817 G4double coilHeightFraction,
818 G4double& cShapeOuterEdge,
819 G4double& poleHalfGap,
821 G4double& poleHeight,
823 G4double& yokeHalfHeight,
824 G4double& yokeThickness,
825 G4double& yokeOverHang,
827 G4double& coilHeightIn,
828 G4double& coilToYokeGap,
829 G4double& coilToPoleGap,
831 G4double& containerSLength,
832 G4double& intersectionRadius)
836 G4double vhRatioL = buildVertically ? 1./vhRatio : vhRatio;
838 G4double horizontalSize = buildVertically ? vhRatio * horizontalWidth : horizontalWidth;
841 G4double bpHalfWidth = beamPipe->
GetExtent().MaximumX();
842 G4double bpHalfHeight = beamPipe->
GetExtent().MaximumY();
846 {std::swap(bpHalfWidth, bpHalfHeight);}
851 poleWidth = std::max(poleWidth, horizontalSize*0.36);
853 if (poleWidth > 0.9*horizontalSize)
854 {poleWidth = horizontalSize*0.7;}
859 cShapeOuterEdge = std::max(cShapeOuterEdge, 0.5 * poleWidth);
865 yokeWidth = horizontalSize;
866 G4double yokeHeight = horizontalSize * vhRatioL;
872 const G4double margin = 50*CLHEP::um;
873 G4double yokeWidthLowerLimit = 2 * bpHalfWidth + margin;
874 G4double yokeHeightLowerLimit = 2 * bpHalfHeight + margin;
875 if (yokeWidth <= yokeWidthLowerLimit)
876 {yokeWidth = yokeWidthLowerLimit + margin;}
877 if (yokeHeight <= yokeHeightLowerLimit)
878 {yokeHeight = yokeHeightLowerLimit + margin;}
881 yokeThickness = yokeThicknessFraction * horizontalSize;
892 G4double factor = hStyle ? 2.0 : 1.0;
893 if (factor * yokeThickness > yokeWidth - poleWidth)
896 yokeThickness = (yokeWidth - poleWidth) / factor;
900 if (factor * yokeThickness > yokeWidth - 2 * bpHalfWidth)
903 yokeThickness = (yokeWidth - 2 * bpHalfWidth) / factor;
907 {poleHeight = 0.5 * yokeHeight - yokeThickness - poleHalfGap;}
912 G4double yokeThicknessLimitHorizontal = yokeWidth - yokeWidthLowerLimit - margin*0.5;
913 G4double yokeThicknessLimitVertical = 0.5 * yokeHeight - yokeHeightLowerLimit - margin;
914 G4double yokeThicknessLimit = std::min(yokeThicknessLimitHorizontal, 2*yokeThicknessLimitVertical);
915 if (yokeThickness > yokeThicknessLimit)
916 {yokeThickness = yokeThicknessLimit;}
917 if (yokeThickness < margin)
918 {yokeThickness = margin;}
921 yokeHalfHeight = 0.5 * yokeHeight;
925 if (yokeThickness + poleWidth > horizontalSize - margin)
926 {yokeThickness = horizontalWidth - poleWidth - margin;}
929 {yokeOverHang = 0.5*yokeWidth - yokeThickness - 0.5*poleWidth;}
931 {yokeOverHang = yokeWidth - yokeThickness - poleWidth;}
941 containerSLength = sLength;
943 intersectionRadius = std::hypot(0.5*poleWidth + yokeOverHang, poleHalfGap + poleHeight);
945 if (yokeThickness > 0.05*horizontalSize)
946 {intersectionRadius += 0.8 * std::hypot(yokeThickness, yokeThickness);}
948 {intersectionRadius *= 1.3;}
950 coilWidth = yokeOverHang * coilWidthFraction;
951 coilHeightIn = poleHeight * coilHeightFraction;
952 coilToYokeGap = (poleHeight - coilHeightIn) * 0.5;
957 G4double poleHalfGapIn,
958 G4double coilWidthIn,
959 G4double coilHeightIn,
967 G4ThreeVector coilTLDisp = G4ThreeVector( coilDX, coilDY, 0);
968 G4ThreeVector coilTRDisp = G4ThreeVector(-coilDX, coilDY, 0);
969 G4ThreeVector coilBLDisp = G4ThreeVector( coilDX,-coilDY, 0);
970 G4ThreeVector coilBRDisp = G4ThreeVector(-coilDX,-coilDY, 0);
971 std::vector<G4ThreeVector> coilDisps;
972 coilDisps.push_back(coilTLDisp);
973 coilDisps.push_back(coilTRDisp);
974 coilDisps.push_back(coilBLDisp);
975 coilDisps.push_back(coilBRDisp);
982 G4double containerLength,
984 G4bool buildVertically)
986 G4double horizontalWidth = recipe->horizontalWidth;
987 G4double angleIn = recipe->angleIn;
988 G4double angleOut = recipe->angleOut;
989 G4Material* material = recipe->outerMaterial;
990 G4Colour* colour = recipe->colour;
991 G4bool buildEndPiece = recipe->buildEndPieces;
992 G4double vhRatio = recipe->vhRatio;
993 G4double coilWidthFraction = recipe->coilWidthFraction;
994 G4double coilHeightFraction = recipe->coilHeightFraction;
995 G4bool yokeOnLeft = recipe->yokeOnLeft;
1008 G4double cShapeOuterEdge = 0;
1009 G4double poleHalfGap = 0;
1010 G4double poleWidth = 0;
1011 G4double poleHeight = 0;
1012 G4double yokeWidth = 0;
1013 G4double yokeHalfHeight = 0;
1014 G4double yokeThickness = 0;
1015 G4double yokeOverHang = 0;
1016 G4double coilWidth = 0;
1018 G4double coilToYokeGap = 0;
1019 G4double coilToPoleGap = 0;
1020 G4double sLength = length;
1021 G4double containerSLength = containerLength;
1022 G4double intersectionRadius = 0;
1023 DipoleCalculations(
false, buildVertically, beamPipe, length, horizontalWidth, angleIn,
1024 angleOut, 0.23, vhRatio, coilWidthFraction, coilHeightFraction,
1025 cShapeOuterEdge, poleHalfGap, poleWidth, poleHeight,
1026 yokeWidth, yokeHalfHeight, yokeThickness, yokeOverHang, coilWidth,
1028 sLength, containerSLength, intersectionRadius);
1031 G4double yokeInsideX = -0.5*poleWidth - yokeOverHang;
1034 G4double cDY = (poleHeight -
coilHeight)*0.5;
1037 std::vector<G4ThreeVector> coilDisps;
1038 G4double coilDY = 0;
1047 std::vector<G4TwoVector> yokePoints;
1048 std::vector<G4TwoVector> cPoints;
1049 std::vector<G4TwoVector> mCPoints;
1052 G4double extXPos = 0;
1053 G4double extXNeg = 0;
1054 G4double extYPos = 0;
1055 G4double extYNeg = 0;
1063 const G4double phw = 0.5*poleWidth;
1064 const G4double phg = poleHalfGap;
1065 const G4double yw = yokeWidth;
1066 const G4double yhh = yokeHalfHeight;
1067 yokePoints.emplace_back(phw - lsl, phg + lsl);
1068 yokePoints.emplace_back(phw - lsl, yhh - lsl);
1069 yokePoints.emplace_back(phw + lsl - yw, yhh - lsl);
1070 yokePoints.emplace_back(phw + lsl - yw, -yhh + lsl);
1071 yokePoints.emplace_back(phw - lsl, -yhh + lsl);
1072 yokePoints.emplace_back(phw - lsl, -phg - lsl);
1075 yokePoints.emplace_back(-phw + lsl, -phg - lsl);
1076 yokePoints.emplace_back(-phw + lsl, -yhh + yokeThickness);
1077 yokePoints.emplace_back( yokeInsideX - lsl, -yhh + yokeThickness);
1078 yokePoints.emplace_back( yokeInsideX - lsl, yhh - yokeThickness);
1079 yokePoints.emplace_back(-phw + lsl, yhh - yokeThickness);
1080 yokePoints.emplace_back(-phw + lsl, phg + lsl);
1084 yokePoints.emplace_back(yokeInsideX - lsl, -phg - lsl);
1085 yokePoints.emplace_back(yokeInsideX - lsl, phg + lsl);
1090 {cPoints.emplace_back(phw + lsl, phg);}
1093 cPoints.emplace_back(phw + coilWidth + 2*lsl, phg);
1094 cPoints.emplace_back(phw + coilWidth + 2*lsl, phg +
coilHeight + 2*lsl + cDY);
1095 cPoints.emplace_back(phw + lsl, phg +
coilHeight + 2*lsl + cDY);
1097 cPoints.emplace_back(phw + lsl, yhh + lsl);
1098 cPoints.emplace_back(phw - yw - lsl, yhh + lsl);
1099 cPoints.emplace_back(phw - yw - lsl, -yhh - lsl);
1100 cPoints.emplace_back(phw + lsl, -yhh - lsl);
1103 cPoints.emplace_back(phw + lsl, -phg -
coilHeight - 2*lsl - cDY);
1104 cPoints.emplace_back(phw + coilWidth + 2*lsl, -phg -
coilHeight - 2*lsl - cDY);
1105 cPoints.emplace_back(phw + coilWidth + 2*lsl, -phg);
1108 {cPoints.emplace_back(phw + lsl, -phg);}
1109 cPoints.emplace_back(yokeInsideX, -phg);
1110 cPoints.emplace_back(yokeInsideX, phg);
1115 G4double maxLeft = std::max(phw, cShapeOuterEdge);
1116 mCPoints.emplace_back(maxLeft + lsl, phg - lsl);
1119 mCPoints.emplace_back(phw + coilWidth + 4*lsl, phg - lsl);
1120 mCPoints.emplace_back(phw + coilWidth + 4*lsl, phg +
coilHeight + 3*lsl + cDY);
1121 mCPoints.emplace_back(phw + 2*lsl, phg +
coilHeight + 3*lsl + cDY);
1123 mCPoints.emplace_back(phw + 2*lsl, yhh + 2*lsl);
1124 mCPoints.emplace_back(phw - yw - 2*lsl, yhh + 2*lsl);
1125 mCPoints.emplace_back(phw - yw - 2*lsl, -yhh - 2*lsl);
1126 mCPoints.emplace_back(phw + 2*lsl, -yhh - 2*lsl);
1129 mCPoints.emplace_back(phw + 2*lsl, -phg -
coilHeight - 3*lsl - cDY);
1130 mCPoints.emplace_back(phw + coilWidth + 4*lsl, -phg -
coilHeight - 3*lsl - cDY);
1131 mCPoints.emplace_back(phw + coilWidth + 4*lsl, -phg + lsl);
1133 mCPoints.emplace_back(maxLeft + lsl, -phg + lsl);
1136 extXPos = phw + lsl;
1137 extXNeg = phw - yw - 2*lsl;
1138 extYPos = yhh + lsl;
1139 extYNeg = -(yhh +lsl);
1141 {extXPos += coilWidth + lsl;}
1146 for (
auto& vec : yokePoints)
1147 {vec.setX(vec.x() * -1);}
1149 std::reverse(yokePoints.begin(), yokePoints.end());
1152 for (
auto& vec : cPoints)
1153 {vec.setX(vec.x() * -1);}
1154 std::reverse(cPoints.begin(), cPoints.end());
1157 for (
auto& vec : mCPoints)
1158 {vec.setX(vec.x() * -1);}
1159 std::reverse(mCPoints.begin(), mCPoints.end());
1162 std::swap(extXPos, extXNeg);
1166 if (buildVertically)
1168 for (
auto& point : yokePoints)
1170 for (
auto& point : cPoints)
1172 for (
auto& point : mCPoints)
1175 std::swap(extXPos, extYPos);
1176 std::swap(extXNeg, extYNeg);
1180 -length*0.5, length*0.5);
1181 magContExtent = ext;
1183 G4TwoVector zOffsets(0,0);
1184 G4double zScale = 1;
1185 yokeSolid =
new G4ExtrudedSolid(name +
"_yoke_sq_solid",
1192 containerSolid =
new G4ExtrudedSolid(name +
"_outer_sq_container_solid",
1199 magnetContainerSolid =
new G4ExtrudedSolid(name +
"_sq_container_solid",
1201 containerSLength*0.5,
1207 allSolids.insert(containerSolid);
1208 allSolids.insert(magnetContainerSolid);
1210 return DipoleCommonConstruction(name, horizontalWidth, buildEndPiece, coilWidth, length,
1211 containerLength, sLength, angleIn, angleOut,
1213 coilDisps, buildVertically, ext, 0.5*poleWidth, poleHalfGap,
1214 cDY, coilDY, intersectionRadius);
1220 G4double containerLength,
1222 G4bool buildVertically)
1224 G4double horizontalWidth = recipe->horizontalWidth;
1225 G4double angleIn = recipe->angleIn;
1226 G4double angleOut = recipe->angleOut;
1227 G4Material* material = recipe->outerMaterial;
1228 G4Colour* colour = recipe->colour;
1229 G4bool buildEndPiece = recipe->buildEndPieces;
1230 G4double vhRatio = recipe->vhRatio;
1231 G4double coilWidthFraction = recipe->coilWidthFraction;
1232 G4double coilHeightFraction = recipe->coilHeightFraction;
1245 G4double cShapeOuterEdge = 0;
1246 G4double poleHalfGap = 0;
1247 G4double poleWidth = 0;
1248 G4double poleHeight = 0;
1249 G4double yokeWidth = 0;
1250 G4double yokeHalfHeight = 0;
1251 G4double yokeThickness = 0;
1252 G4double yokeOverHang = 0;
1253 G4double coilWidth = 0;
1255 G4double coilToYokeGap = 0;
1256 G4double coilToPoleGap = 0;
1257 G4double sLength = length;
1258 G4double containerSLength = containerLength;
1259 G4double intersectionRadius = 0;
1260 DipoleCalculations(
true, buildVertically, beamPipe, length, horizontalWidth, angleIn,
1261 angleOut, 0.12, vhRatio, coilWidthFraction, coilHeightFraction,
1262 cShapeOuterEdge, poleHalfGap, poleWidth, poleHeight,
1263 yokeWidth, yokeHalfHeight, yokeThickness, yokeOverHang,
1264 coilWidth,
coilHeight, coilToYokeGap, coilToPoleGap,
1265 sLength, containerSLength, intersectionRadius);
1268 G4double yokeInsideX = 0;
1270 {yokeInsideX = 0.5*poleWidth + yokeOverHang;}
1272 {yokeInsideX = 0.5*yokeWidth - yokeThickness;}
1275 G4double yokeInsideY = 0;
1277 {yokeInsideY = poleHalfGap + poleHeight;}
1279 {yokeInsideY = yokeHalfHeight - yokeThickness;}
1282 G4double cDY = (poleHeight -
coilHeight)*0.5;
1287 std::vector<G4ThreeVector> coilDisps;
1288 G4double coilDY = 0;
1297 std::vector<G4TwoVector> yokePoints;
1298 std::vector<G4TwoVector> cPoints;
1299 std::vector<G4TwoVector> mCPoints;
1302 G4double extXPos = 0;
1303 G4double extXNeg = 0;
1304 G4double extYPos = 0;
1305 G4double extYNeg = 0;
1307 G4VSolid* yokeInnerSolid =
nullptr;
1312 const G4double phw = 0.5*poleWidth;
1313 const G4double phg = poleHalfGap;
1314 yokePoints.emplace_back( phw - lsl, phg + lsl);
1315 yokePoints.emplace_back( phw - lsl, yokeInsideY + lsl);
1316 yokePoints.emplace_back( yokeInsideX + lsl, yokeInsideY + lsl);
1317 yokePoints.emplace_back( yokeInsideX + lsl, -yokeInsideY - lsl);
1318 yokePoints.emplace_back( phw - lsl, -yokeInsideY - lsl);
1319 yokePoints.emplace_back( phw - lsl, -phg - lsl);
1320 yokePoints.emplace_back(-phw + lsl, -phg - lsl);
1321 yokePoints.emplace_back(-phw + lsl, -yokeInsideY - lsl);
1322 yokePoints.emplace_back(-yokeInsideX - lsl, -yokeInsideY - lsl);
1323 yokePoints.emplace_back(-yokeInsideX - lsl, yokeInsideY + lsl);
1324 yokePoints.emplace_back(-phw + lsl, yokeInsideY + lsl);
1325 yokePoints.emplace_back(-phw + lsl, phg + lsl);
1328 if (buildVertically)
1330 for (
auto& point : yokePoints)
1334 G4TwoVector zOffsets(0,0);
1335 G4double zScale = 1;
1336 yokeInnerSolid =
new G4ExtrudedSolid(name +
"_yoke_inner_solid",
1345 G4double yIX = buildVertically ? yokeInsideY : yokeInsideX;
1346 G4double yIY = buildVertically ? yokeInsideX : yokeInsideY;
1347 yokeInnerSolid =
new G4Box(name +
"_yoke_inner_solid",
1355 extXPos = 0.5*yokeWidth + lsl;
1356 extXNeg = -0.5*yokeWidth - lsl;
1357 extYPos = 0.5*yokeWidth + lsl;
1358 extYNeg = -0.5*yokeWidth - lsl;
1360 if (buildVertically)
1362 std::swap(extXPos, extYPos);
1363 std::swap(extXNeg, extYNeg);
1367 -length*0.5, length*0.5);
1368 magContExtent = ext;
1370 G4double yokeOuterX = 0.5*yokeWidth - lsl;
1371 G4double yokeOuterY = yokeHalfHeight - lsl;
1372 G4double yOX = buildVertically ? yokeOuterY : yokeOuterX;
1373 G4double yOY = buildVertically ? yokeOuterX : yokeOuterY;
1374 G4VSolid* yokeOuterSolid =
new G4Box(name +
"_yoke_outer_solid",
1377 sLength * 0.5 - lsl);
1379 yokeSolid =
new G4SubtractionSolid(name +
"_yoke_solid",
1384 G4double containerdx = 0.5 * yokeWidth - yokeThickness - lsl;
1385 G4double containerdy = poleHalfGap;
1386 if (buildVertically)
1387 {std::swap(containerdx, containerdy);}
1390 G4VSolid* containerInnerSolid =
new G4Box(name +
"_container_inner_solid",
1394 G4double cOX = 0.5 * yokeWidth;
1395 G4double cOY = yokeHalfHeight;
1396 if (buildVertically)
1397 {std::swap(cOX, cOY);}
1398 G4VSolid* containerOuterSolid =
new G4Box(name +
"_container_outer_solid",
1403 containerSolid =
new G4SubtractionSolid(name +
"_outer_sq_container_solid",
1404 containerOuterSolid,
1405 containerInnerSolid);
1408 magnetContainerSolid =
new G4Box(name +
"_sq_container_solid",
1411 containerSLength * 0.5);
1414 allSolids.insert(yokeInnerSolid);
1415 allSolids.insert(yokeOuterSolid);
1417 allSolids.insert(containerInnerSolid);
1418 allSolids.insert(containerOuterSolid);
1419 allSolids.insert(containerSolid);
1420 allSolids.insert(magnetContainerSolid);
1422 return DipoleCommonConstruction(name, horizontalWidth, buildEndPiece, coilWidth, length,
1423 containerLength, sLength, angleIn, angleOut,
1425 coilDisps, buildVertically, ext, poleWidth*0.5, poleHalfGap,
1426 cDY, coilDY, intersectionRadius);
1429BDSMagnetOuter* BDSMagnetOuterFactoryPolesBase::DipoleCommonConstruction(
const G4String& name,
1430 G4double horizontalWidth,
1431 G4bool buildEndPiece,
1434 G4double containerLength,
1439 G4Material* material,
1440 std::vector<G4ThreeVector>& coilDisps,
1441 G4bool buildVertically,
1443 G4double poleHalfWidth,
1444 G4double poleHalfGap,
1447 G4double intersectionRadius)
1455 G4VSolid* coilSolid =
nullptr;
1456 std::vector<G4VSolid*> coilsSolids;
1457 std::vector<G4LogicalVolume*> coilLVs;
1458 G4bool individualCoilsSolids =
false;
1461 G4double cx = 0.5 * coilWidth - lsl;
1463 coilSolid =
new G4Box(name +
"_coil_solid",
1466 sLength*0.5 - 2*lsl);
1467 allSolids.insert(coilSolid);
1475 inputFaceNormal = faces.first;
1476 outputFaceNormal = faces.second;
1479 G4VSolid* angledFaces =
new G4CutTubs(name +
"_angled_face_solid",
1489 G4VSolid* angledFacesCont =
new G4CutTubs(name +
"_angled_face_cont_solid",
1499 G4VSolid* angledFacesMagCont =
new G4CutTubs(name +
"_angled_face_mag_cont_solid",
1502 containerLength*0.5,
1509 allSolids.insert(angledFaces);
1510 allSolids.insert(angledFacesCont);
1511 allSolids.insert(angledFacesMagCont);
1514 yokeSolid =
new G4IntersectionSolid(name +
"_yoke_solid",
1518 containerSolid =
new G4IntersectionSolid(name +
"_outer_container_solid",
1522 magnetContainerSolid =
new G4IntersectionSolid(name +
"_container_solid",
1523 magnetContainerSolid,
1524 angledFacesMagCont);
1526 individualCoilsSolids =
true;
1529 for (G4int i = 0; i < 4; i++)
1531 G4VSolid* coilS =
new G4IntersectionSolid(name +
"_pole_solid_" + std::to_string(i),
1534 (G4RotationMatrix *)
nullptr,
1536 coilsSolids.push_back(coilS);
1537 allSolids.insert(coilS);
1545 G4LogicalVolume* coilLV =
nullptr;
1549 G4VisAttributes* coilVis =
new G4VisAttributes(*coil);
1550 coilVis->SetVisibility(
true);
1551 allVisAttributes.insert(coilVis);
1553 if (individualCoilsSolids)
1555 for (G4int i = 0; i < 4; i++)
1557 G4String theName = name +
"_coil_solid_" + std::to_string(i);
1558 G4LogicalVolume* aCoilLV =
new G4LogicalVolume(coilsSolids[i],
1561 aCoilLV->SetVisAttributes(coilVis);
1562 coilLVs.push_back(aCoilLV);
1563 allLogicalVolumes.insert(aCoilLV);
1568 coilLV =
new G4LogicalVolume(coilSolid,
1571 coilLV->SetVisAttributes(coilVis);
1572 allLogicalVolumes.insert(coilLV);
1577 for (
auto& lv : coilLVs)
1591 G4PVPlacement* aCoilPV =
nullptr;
1595 for (G4int i = 0; i < 4; i++)
1597 G4LogicalVolume* volToPlace = coilLV;
1598 G4ThreeVector displacement = G4ThreeVector();
1599 if (individualCoilsSolids)
1600 {volToPlace = coilLVs[i];}
1602 {displacement = coilDisps[i];}
1603 G4String theName = name +
"_coil_" + std::to_string(i) +
"_pv";
1604 if (buildVertically)
1606 G4RotationMatrix* rotVert =
new G4RotationMatrix();
1607 rotVert->rotateZ(CLHEP::halfpi);
1608 displacement.transform(*rotVert);
1611 aCoilPV =
new G4PVPlacement(
nullptr,
1619 allPhysicalVolumes.insert(aCoilPV);
1624 CreateMagnetContainerComponent();
1650 if (individualCoilsSolids)
1652 std::set<G4LogicalVolume*> tempLVs(coilLVs.begin(), coilLVs.end());
1672 std::vector<G4TwoVector> inEPPoints;
1673 std::vector<G4TwoVector> outEPPoints;
1675 G4double inXO = poleHalfWidth - lsl;
1679 G4double increment = CLHEP::halfpi/nSegments;
1680 G4double epWidth = buildVertically ?
coilHeight : coilWidth;
1681 for (G4double t = -CLHEP::pi; t <= -CLHEP::halfpi + 1e-9; t += increment)
1683 G4double x = -inXO + epWidth*std::cos(t);
1684 G4double y = epWidth*std::sin(t);
1685 inEPPoints.emplace_back(x,y);
1688 for (G4double t = -CLHEP::halfpi; t <= 0 + 1e-9; t += increment)
1690 G4double x = inXO + epWidth*std::cos(t);
1691 G4double y = epWidth*std::sin(t);
1692 inEPPoints.emplace_back(x,y);
1700 for (
const auto& point : inEPPoints)
1702 G4double outy = -1*(point.x()*std::tan(-angleOut) + point.y());
1703 outEPPoints.emplace_back(point.x(),outy);
1705 for (
auto& point : inEPPoints)
1706 {point.setY(point.x()*std::tan(-angleIn) + point.y());}
1708 G4TwoVector zOffsets(0,0);
1709 G4double zScale = 1;
1712 G4double epHeight = buildVertically ? coilWidth :
coilHeight;
1713 G4VSolid* endPieceSolidIn =
new G4ExtrudedSolid(name +
"_end_coil_in_solid",
1715 0.5 * epHeight - lsl,
1720 G4VSolid* endPieceSolidOut =
new G4ExtrudedSolid(name +
"_end_coil_out_solid",
1722 0.5 * epHeight - lsl,
1728 std::vector<G4TwoVector> contEPPoints;
1729 const G4double connector = 1*CLHEP::mm;
1730 G4double xmax = poleHalfWidth + epWidth + lsl;
1731 G4double ymax = poleHalfGap + epHeight + cDY + lsl;
1732 G4double yInn = poleHalfGap + cDY - lsl;
1733 contEPPoints.emplace_back(xmax + connector, ymax);
1734 contEPPoints.emplace_back(-xmax, ymax);
1735 contEPPoints.emplace_back(-xmax, yInn);
1736 contEPPoints.emplace_back( xmax, yInn);
1737 contEPPoints.emplace_back( xmax, -yInn);
1738 contEPPoints.emplace_back(-xmax, -yInn);
1739 contEPPoints.emplace_back(-xmax, -ymax);
1740 contEPPoints.emplace_back(xmax + connector, -ymax);
1742 G4double containerIntersectionRadius = std::hypot(ymax, xmax);
1744 if (buildVertically)
1746 for (
auto& point : contEPPoints)
1752 G4double ePInLengthZ = ePInLength;
1755 G4double dzIn = std::tan(std::abs(angleIn)) * horizontalWidth;
1756 ePInLength = std::max(2*ePInLength, 2*dzIn);
1761 -ePInLengthZ*0.5, ePInLengthZ*0.5);
1764 -ePInLengthZ*0.5, ePInLengthZ*0.5);
1766 G4VSolid* ePContSolidIn =
new G4ExtrudedSolid(name +
"_end_coil_in_solid",
1768 0.5*ePInLength + lsl,
1773 G4double ePOutLengthZ = ePOutLength;
1776 G4double dzOut = std::tan(std::abs(angleOut)) * horizontalWidth;
1777 ePOutLength = std::max(2*ePOutLength, 2*dzOut);
1780 G4VSolid* ePContSolidOut =
new G4ExtrudedSolid(name +
"_end_coil_out_solid",
1791 G4ThreeVector inputfaceReversed = inputFaceNormal * -1;
1792 G4VSolid* ePContSolidInAng =
new G4CutTubs(name +
"_angled_face_solid",
1794 containerIntersectionRadius,
1802 ePContSolidIn =
new G4IntersectionSolid(name +
"_end_coil_cont_solid",
1810 G4ThreeVector outputfaceReversed = outputFaceNormal * -1;
1811 G4VSolid* ePContSolidOutAng =
new G4CutTubs(name +
"_angled_face_solid",
1813 containerIntersectionRadius,
1821 ePContSolidOut =
new G4IntersectionSolid(name +
"_end_coil_cont_solid",
1831 G4LogicalVolume* ePInLV =
new G4LogicalVolume(endPieceSolidIn,
1833 name +
"_end_coil_in_lv");
1835 G4LogicalVolume* ePContInLV =
new G4LogicalVolume(ePContSolidIn,
1837 name +
"_end_cont_in_lv");
1839 G4LogicalVolume* ePOutLV =
new G4LogicalVolume(endPieceSolidOut,
1841 name +
"_end_coil_out_lv");
1843 G4LogicalVolume* ePContOutLV =
new G4LogicalVolume(ePContSolidOut,
1845 name +
"_end_cont_out_lv");
1848 G4VisAttributes* coilVisIn =
new G4VisAttributes(*coilColour);
1849 coilVisIn->SetVisibility(
true);
1850 G4VisAttributes* coilVisOut =
new G4VisAttributes(*coilVisIn);
1852 ePInLV->SetVisAttributes(coilVisIn);
1853 ePOutLV->SetVisAttributes(coilVisOut);
1863 G4RotationMatrix* endCoilInRM =
new G4RotationMatrix();
1864 endCoilInRM->rotateX(-CLHEP::halfpi);
1865 if (buildVertically)
1866 {endCoilInRM->rotate(CLHEP::halfpi, G4ThreeVector(0,1,0));}
1867 G4ThreeVector endCoilTranslationInTop(0, coilDY-lsl, 0.5*epWidth);
1868 G4ThreeVector endCoilTranslationInLow(0,-coilDY+lsl, 0.5*epWidth);
1869 G4RotationMatrix* vertRot =
new G4RotationMatrix();
1870 vertRot->rotateZ(CLHEP::halfpi);
1871 if (buildVertically)
1873 endCoilTranslationInTop.transform(*vertRot);
1874 endCoilTranslationInLow.transform(*vertRot);
1878 G4PVPlacement* ePInTopPv =
new G4PVPlacement(endCoilInRM,
1879 endCoilTranslationInTop,
1881 name +
"_end_piece_in_top_pv",
1886 G4PVPlacement* ePInLowPv =
new G4PVPlacement(endCoilInRM,
1887 endCoilTranslationInLow,
1889 name +
"_end_piece_in_low_pv",
1895 G4RotationMatrix* endCoilOutRM =
new G4RotationMatrix(*endCoilInRM);
1897 G4ThreeVector endCoilTranslationOutTop(0, coilDY, -0.5*epWidth);
1898 G4ThreeVector endCoilTranslationOutLow(0,-coilDY, -0.5*epWidth);
1899 if (buildVertically)
1901 endCoilTranslationOutTop.transform(*vertRot);
1902 endCoilTranslationOutLow.transform(*vertRot);
1906 G4PVPlacement* ePOutTopPv =
new G4PVPlacement(endCoilOutRM,
1907 endCoilTranslationOutTop,
1909 name +
"_end_piece_out_top_pv",
1914 G4PVPlacement* ePOutLowPv =
new G4PVPlacement(endCoilOutRM,
1915 endCoilTranslationOutLow,
1917 name +
"_end_piece_out_low_pv",
1924 G4ThreeVector inputFaceNormalR = inputFaceNormal * -1;
1944 G4ThreeVector outputFaceNormalR = outputFaceNormal * -1;
1966 outer->SetEndPieceBefore(endPieceInSC);
1967 outer->SetEndPieceAfter(endPieceOutSC);
A holder class for a piece of beam pipe geometry.
G4double GetContainerRadius() const
If it is circular, we need the radius.
static BDSColours * Instance()
singleton pattern
G4Colour * GetColour(const G4String &type, G4bool normaliseTo255=true)
Get colour from name.
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.