/scratch0/jsnuveri/BDSIM/BDSIMgit/bdsim/src/BDSMagnetOuterFactoryPolesSquare.cc

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   // full circle is divided into segments for each pole
00063   G4double segmentAngleWidth = CLHEP::twopi / (G4double)nPoles;
00064   G4double poleAngle = segmentAngleWidth * poleAngularFraction;
00065 
00066   // compose pole of an annulus of a certain angle plus
00067   // an ellipsoid at the inner side. make the union of the
00068   // two to give a typical pole shape - curved inner surface
00069   // with increasing width outwards
00070   
00071   // make some % of pole length curved ellipsoidal surface
00072 
00073   G4double  croppingBoxRadius = yokeStartRadius - lengthSafety;
00074   G4VSolid* croppingBoxSolid = new G4Box(name + "_pole_intersection_solid", // name
00075                                          croppingBoxRadius,                 // x half width
00076                                          croppingBoxRadius,                 // y half width
00077                                          length);                           // z length
00078   // z length long for unambiguous intersection
00079   
00080   G4double poleLength          = poleFinishRadius - poleStartRadius - 2*lengthSafety;
00081   G4double ellipsoidHeight     = poleTipFraction*poleLength;
00082   //G4double annulusHeight       = poleLength - ellipsoidHeight;
00083   G4double ellipsoidCentre     = poleStartRadius + ellipsoidHeight*0.5;
00084   
00085   // work out the chord length
00086   G4double ellipsoidWidth      = 2*(poleStartRadius + 0.5*ellipsoidHeight) * tan(poleAngle*0.5);
00087   
00088   G4double annulusStartRadius  = ellipsoidCentre / cos(poleAngle*0.5); //so edges line up with ellipsoid edges
00089   G4double annulusFinishRadius = poleFinishRadius*2; // long for unambiguous intersection with yoke
00090 
00091   G4VSolid* poleTip = new G4EllipticalTube(name + "_pole_tip_solid",   // name
00092                                                ellipsoidHeight*0.5,        // x half width
00093                                                ellipsoidWidth*0.5,         // y half width
00094                                                length*0.5 - lengthSafety); // z half width
00095 
00096   G4VSolid* poleAnnulus = new G4Tubs(name + "_pole_annulus_solid", // name
00097                                      annulusStartRadius,           // start radius
00098                                      annulusFinishRadius,          // finish radius
00099                                      length*0.5 - lengthSafety,    // z half length
00100                                      -poleAngle*0.5,               // start angle
00101                                      poleAngle);                   // sweep angle
00102   
00103   // note annulus is defined from centre of rotation
00104   G4ThreeVector ellipsoidTranslation(poleStartRadius + ellipsoidHeight*0.5, 0, 0);
00105   // the centre of the union solid will be that of the 1st solid - the annulus - ie 0,0,0
00106   G4VSolid* aSinglePoleSolid = new G4UnionSolid(name + "_pole_solid", // name
00107                                                 poleAnnulus,          // solid 1
00108                                                 poleTip,              // solid 2
00109                                                 0,                    // rotation matrix
00110                                                 ellipsoidTranslation);// translation of poleTip
00111   
00112   // create different poles to fit inside square yoke
00113   G4RotationMatrix* iPoleRM;
00114   for (G4int i = 0; i < nPoles; ++i)
00115     {
00116       iPoleRM = new G4RotationMatrix();
00117       G4double segmentAngle = CLHEP::twopi/nPoles; // angle per pole
00118       G4double rotationAngle = (0.5-i)*segmentAngle + CLHEP::pi*0.5;
00119       iPoleRM->rotateZ(rotationAngle); 
00120       // crop the singlepolesolid with the cropping box so it'll fit inside the outer square yoke
00121       G4IntersectionSolid* aSolid = new G4IntersectionSolid(name + "_pole_solid", // name
00122                                                             aSinglePoleSolid,
00123                                                             croppingBoxSolid,     // solid 2 - the one to be shifted
00124                                                             iPoleRM,              // rotation matrix
00125                                                             (G4ThreeVector)0);    // translation vector
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         /*order*/)
00137 {
00138   // square yoke - have to do subtraction between two solid boxes
00139   G4VSolid* yokeOuter = new G4Box(name + "_yoke_outer_solid", // name
00140                                   yokeFinishRadius,           // x half width
00141                                   yokeFinishRadius,           // y half width
00142                                   length*0.5 - lengthSafety); // z half length
00143 
00144   G4VSolid* yokeInner = new G4Box(name + "_yoke_inner_solid", // name
00145                                   yokeStartRadius,            // x half width
00146                                   yokeStartRadius,            // y half width
00147                                   length);                    // z half length
00148   // inner length is 2x as long for unambiguous subtraction
00149 
00150   yokeSolid = new G4SubtractionSolid(name + "_yoke_solid",    // name
00151                                      yokeOuter,
00152                                      yokeInner);
00153 
00154   // note container must have hole in it for the beampipe to fit in!
00155   // poled geometry doesn't fit tightly to beampipe so can alays use a circular aperture
00156 
00157   G4VSolid* containerOuter = new G4Box(name + "_container_outer_solid", // name
00158                                        yokeFinishRadius,                // x half width
00159                                        yokeFinishRadius,                // y half width
00160                                        length*0.5);                     // x half width
00161 
00162   G4VSolid* containerInner = new G4Tubs(name + "_container_inner_solid", // name
00163                                         0,                               // inner radius
00164                                         poleStartRadius,                 // finish radius
00165                                         length,                          // z half length
00166                                         0,                               // start angle
00167                                         CLHEP::twopi);                   // sweep angle
00168   // length of inner is long for unambiguous subtraction
00169 
00170   containerSolid = new G4SubtractionSolid(name + "_container_solid", // name
00171                                           containerOuter,
00172                                           containerInner);
00173 }
00174 
00175 void BDSMagnetOuterFactoryPolesSquare::CreateLogicalVolumes(G4String    name,
00176                                                             G4double    length,
00177                                                             G4int       order,
00178                                                             G4Material* outerMaterial)
00179 {
00180   // VISUAL ATTRIBUTES
00181   // set visual attributes
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   // yoke
00197   yokeLV   = new G4LogicalVolume(yokeSolid,
00198                                  outerMaterial,
00199                                  name + "_yoke_lv");
00200   yokeLV->SetVisAttributes(outerVisAttr);
00201 
00202   // container
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   // USER LIMITS
00213   // set user limits based on bdsim user specified parameters
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   //attach cuts to volumes
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   // PLACEMENT
00234   // place the components inside the container
00235   // note we don't need the pointer for placements - it's registered upon construction with g4
00236   new G4PVPlacement((G4RotationMatrix*)0,         // no rotation
00237                     (G4ThreeVector)0,             // position
00238                     yokeLV,                       // lv to be placed
00239                     name + "_yoke_pv",            // name
00240                     containerLV,                  // mother lv to be placed in
00241                     false,                        // no boolean operation
00242                     0,                            // copy number
00243                     checkOverlaps);               // whether to check overlaps
00244   
00245   // pole placement
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; // angle per pole
00251       G4double rotationAngle = (0.5-n)*segmentAngle + CLHEP::pi*0.5;
00252       rm->rotateZ(-rotationAngle); 
00253       // only need to test the end of one iterator as both should be the same length
00254       new G4PVPlacement(rm,                 // rotation
00255                         (G4ThreeVector)0,   // position
00256                         poleLVs[n],         // logical volume
00257                         name + "_pole_pv",  // name      
00258                         containerLV,        // mother lv to be placed in
00259                         false,              // no boolean operation
00260                         n,                  // copy number
00261                         checkOverlaps);     // check overlaps
00262       //name + "_pole_" + printf("_%d_pv", n), // name
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   // sensitive volumes
00281   outer->RegisterSensitiveVolumes(poleLVs);
00282   outer->RegisterSensitiveVolume(yokeLV);
00283   
00284   return outer;
00285 }
00286   

Generated on 28 Jun 2015 for BDSIM by  doxygen 1.4.7