00001 #include "BDSMagnetOuterFactoryPolesSquare.hh"
00002
00003 #include "BDSBeamPipe.hh"
00004 #include "BDSExecOptions.hh"
00005 #include "BDSGeometryComponent.hh"
00006 #include "BDSGlobalConstants.hh"
00007 #include "BDSMaterials.hh"
00008 #include "BDSMagnetColours.hh"
00009 #include "BDSSDManager.hh"
00010
00011 #include "globals.hh"
00012
00013 #include "G4Box.hh"
00014 #include "G4EllipticalTube.hh"
00015 #include "G4IntersectionSolid.hh"
00016 #include "G4LogicalVolume.hh"
00017 #include "G4Material.hh"
00018 #include "G4PVPlacement.hh"
00019 #include "G4SubtractionSolid.hh"
00020 #include "G4Tubs.hh"
00021 #include "G4UnionSolid.hh"
00022 #include "G4UserLimits.hh"
00023 #include "G4VisAttributes.hh"
00024 #include "G4VSolid.hh"
00025
00026 #include <vector>
00027 #include <cmath>
00028
00029 BDSMagnetOuterFactoryPolesSquare* BDSMagnetOuterFactoryPolesSquare::_instance = 0;
00030
00031 BDSMagnetOuterFactoryPolesSquare* BDSMagnetOuterFactoryPolesSquare::Instance()
00032 {
00033 if (_instance == 0)
00034 {_instance = new BDSMagnetOuterFactoryPolesSquare();}
00035 return _instance;
00036 }
00037
00038 BDSMagnetOuterFactoryPolesSquare::BDSMagnetOuterFactoryPolesSquare()
00039 {
00040 CleanUp();
00041 }
00042
00043 BDSMagnetOuterFactoryPolesSquare::~BDSMagnetOuterFactoryPolesSquare()
00044 {
00045 _instance = 0;
00046 }
00047
00048 void BDSMagnetOuterFactoryPolesSquare::CleanUp()
00049 {
00050 BDSMagnetOuterFactoryPolesBase::CleanUp();
00051 poleRotations.clear();
00052 poleSolids.clear();
00053 poleLVs.clear();
00054 }
00055
00056 void BDSMagnetOuterFactoryPolesSquare::CreatePoleSolid(G4String name,
00057 G4double length,
00058 G4int order)
00059 {
00060 G4int nPoles = 2*order;
00061
00062
00063 G4double segmentAngleWidth = CLHEP::twopi / (G4double)nPoles;
00064 G4double poleAngle = segmentAngleWidth * poleAngularFraction;
00065
00066
00067
00068
00069
00070
00071
00072
00073 G4double croppingBoxRadius = yokeStartRadius - lengthSafety;
00074 G4VSolid* croppingBoxSolid = new G4Box(name + "_pole_intersection_solid",
00075 croppingBoxRadius,
00076 croppingBoxRadius,
00077 length);
00078
00079
00080 G4double poleLength = poleFinishRadius - poleStartRadius - 2*lengthSafety;
00081 G4double ellipsoidHeight = poleTipFraction*poleLength;
00082
00083 G4double ellipsoidCentre = poleStartRadius + ellipsoidHeight*0.5;
00084
00085
00086 G4double ellipsoidWidth = 2*(poleStartRadius + 0.5*ellipsoidHeight) * tan(poleAngle*0.5);
00087
00088 G4double annulusStartRadius = ellipsoidCentre / cos(poleAngle*0.5);
00089 G4double annulusFinishRadius = poleFinishRadius*2;
00090
00091 G4VSolid* poleTip = new G4EllipticalTube(name + "_pole_tip_solid",
00092 ellipsoidHeight*0.5,
00093 ellipsoidWidth*0.5,
00094 length*0.5 - lengthSafety);
00095
00096 G4VSolid* poleAnnulus = new G4Tubs(name + "_pole_annulus_solid",
00097 annulusStartRadius,
00098 annulusFinishRadius,
00099 length*0.5 - lengthSafety,
00100 -poleAngle*0.5,
00101 poleAngle);
00102
00103
00104 G4ThreeVector ellipsoidTranslation(poleStartRadius + ellipsoidHeight*0.5, 0, 0);
00105
00106 G4VSolid* aSinglePoleSolid = new G4UnionSolid(name + "_pole_solid",
00107 poleAnnulus,
00108 poleTip,
00109 0,
00110 ellipsoidTranslation);
00111
00112
00113 G4RotationMatrix* iPoleRM;
00114 for (G4int i = 0; i < nPoles; ++i)
00115 {
00116 iPoleRM = new G4RotationMatrix();
00117 G4double segmentAngle = CLHEP::twopi/nPoles;
00118 G4double rotationAngle = (0.5-i)*segmentAngle + CLHEP::pi*0.5;
00119 iPoleRM->rotateZ(rotationAngle);
00120
00121 G4IntersectionSolid* aSolid = new G4IntersectionSolid(name + "_pole_solid",
00122 aSinglePoleSolid,
00123 croppingBoxSolid,
00124 iPoleRM,
00125 (G4ThreeVector)0);
00126
00127
00128 poleSolids.push_back(aSolid);
00129
00130 poleRotations.push_back(iPoleRM);
00131 }
00132 }
00133
00134 void BDSMagnetOuterFactoryPolesSquare::CreateYokeAndContainerSolid(G4String name,
00135 G4double length,
00136 G4int )
00137 {
00138
00139 G4VSolid* yokeOuter = new G4Box(name + "_yoke_outer_solid",
00140 yokeFinishRadius,
00141 yokeFinishRadius,
00142 length*0.5 - lengthSafety);
00143
00144 G4VSolid* yokeInner = new G4Box(name + "_yoke_inner_solid",
00145 yokeStartRadius,
00146 yokeStartRadius,
00147 length);
00148
00149
00150 yokeSolid = new G4SubtractionSolid(name + "_yoke_solid",
00151 yokeOuter,
00152 yokeInner);
00153
00154
00155
00156
00157 G4VSolid* containerOuter = new G4Box(name + "_container_outer_solid",
00158 yokeFinishRadius,
00159 yokeFinishRadius,
00160 length*0.5);
00161
00162 G4VSolid* containerInner = new G4Tubs(name + "_container_inner_solid",
00163 0,
00164 poleStartRadius,
00165 length,
00166 0,
00167 CLHEP::twopi);
00168
00169
00170 containerSolid = new G4SubtractionSolid(name + "_container_solid",
00171 containerOuter,
00172 containerInner);
00173 }
00174
00175 void BDSMagnetOuterFactoryPolesSquare::CreateLogicalVolumes(G4String name,
00176 G4double length,
00177 G4int order,
00178 G4Material* outerMaterial)
00179 {
00180
00181
00182 G4Colour* magnetColour = BDSMagnetColours::Instance()->GetMagnetColour(order);
00183 G4VisAttributes* outerVisAttr = new G4VisAttributes(*magnetColour);
00184 outerVisAttr->SetVisibility(true);
00185 outerVisAttr->SetForceLineSegmentsPerCircle(nSegmentsPerCircle);
00186
00187 for (G4int n = 0; n < 2*order; ++n)
00188 {
00189 G4LogicalVolume* thisPole = new G4LogicalVolume(poleSolids[n],
00190 outerMaterial,
00191 name + "_pole_lv");
00192 thisPole->SetVisAttributes(outerVisAttr);
00193 poleLVs.push_back(thisPole);
00194 }
00195
00196
00197 yokeLV = new G4LogicalVolume(yokeSolid,
00198 outerMaterial,
00199 name + "_yoke_lv");
00200 yokeLV->SetVisAttributes(outerVisAttr);
00201
00202
00203 G4Material* emptyMaterial = BDSMaterials::Instance()->GetMaterial(BDSGlobalConstants::Instance()->GetEmptyMaterial());
00204 containerLV = new G4LogicalVolume(containerSolid,
00205 emptyMaterial,
00206 name + "_container_lv");
00207 if (BDSExecOptions::Instance()->GetVisDebug())
00208 {containerLV->SetVisAttributes(BDSGlobalConstants::Instance()->GetVisibleDebugVisAttr());}
00209 else
00210 {containerLV->SetVisAttributes(BDSGlobalConstants::Instance()->GetInvisibleVisAttr());}
00211
00212
00213
00214 #ifndef NOUSERLIMITS
00215 G4UserLimits* outerUserLimits = new G4UserLimits("outer_cuts");
00216 outerUserLimits->SetMaxAllowedStep( length * maxStepFactor );
00217 outerUserLimits->SetUserMinEkine(BDSGlobalConstants::Instance()->GetThresholdCutCharged());
00218 outerUserLimits->SetUserMaxTime(BDSGlobalConstants::Instance()->GetMaxTime());
00219
00220 yokeLV->SetUserLimits(outerUserLimits);
00221 containerLV->SetUserLimits(outerUserLimits);
00222 std::vector<G4LogicalVolume*>::iterator j;
00223 for(j = poleLVs.begin(); j != poleLVs.end(); ++j)
00224 {
00225 (*j)->SetUserLimits(outerUserLimits);
00226 }
00227 #endif
00228 }
00229
00230 void BDSMagnetOuterFactoryPolesSquare::PlaceComponents(G4String name,
00231 G4int order)
00232 {
00233
00234
00235
00236 new G4PVPlacement((G4RotationMatrix*)0,
00237 (G4ThreeVector)0,
00238 yokeLV,
00239 name + "_yoke_pv",
00240 containerLV,
00241 false,
00242 0,
00243 checkOverlaps);
00244
00245
00246 G4double nPoles = 2*order;
00247 for (G4int n = 0; n < 2*order; ++n)
00248 {
00249 G4RotationMatrix* rm = new G4RotationMatrix();
00250 G4double segmentAngle = CLHEP::twopi/nPoles;
00251 G4double rotationAngle = (0.5-n)*segmentAngle + CLHEP::pi*0.5;
00252 rm->rotateZ(-rotationAngle);
00253
00254 new G4PVPlacement(rm,
00255 (G4ThreeVector)0,
00256 poleLVs[n],
00257 name + "_pole_pv",
00258 containerLV,
00259 false,
00260 n,
00261 checkOverlaps);
00262
00263 }
00264 }
00265
00266 BDSGeometryComponent* BDSMagnetOuterFactoryPolesSquare::CommonConstructor(G4String name,
00267 G4double length,
00268 BDSBeamPipe* beamPipe,
00269 G4int order,
00270 G4double outerDiameter,
00271 G4Material* outerMaterial)
00272 {
00273 BDSGeometryComponent* outer = BDSMagnetOuterFactoryPolesBase::CommonConstructor(name, length, beamPipe,
00274 order, outerDiameter,
00275 outerMaterial);
00276
00277 outer->RegisterLogicalVolumes(poleLVs);
00278 outer->RegisterLogicalVolume(yokeLV);
00279
00280
00281 outer->RegisterSensitiveVolumes(poleLVs);
00282 outer->RegisterSensitiveVolume(yokeLV);
00283
00284 return outer;
00285 }
00286