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

00001 #include "BDSMagnetOuterFactoryCylindrical.hh"
00002 
00003 #include "BDSBeamPipe.hh"
00004 #include "BDSDebug.hh"
00005 #include "BDSExecOptions.hh"
00006 #include "BDSGeometryComponent.hh"
00007 #include "BDSGlobalConstants.hh"
00008 #include "BDSMagnetColours.hh"
00009 #include "BDSMaterials.hh"
00010 #include "BDSSDManager.hh"
00011 #include "BDSUtilities.hh"                 // for calculateorientation
00012 
00013 #include "globals.hh"                      // geant4 globals / types
00014 #include "G4Colour.hh"
00015 #include "G4CutTubs.hh"
00016 #include "G4LogicalVolume.hh"
00017 #include "G4Material.hh"
00018 #include "G4PVPlacement.hh"
00019 #include "G4SubtractionSolid.hh"
00020 #include "G4ThreeVector.hh"
00021 #include "G4Tubs.hh"
00022 #include "G4UserLimits.hh"
00023 #include "G4VisAttributes.hh"
00024 #include "G4VSolid.hh"
00025 
00026 #include <cmath>
00027 #include <utility>                         // for std::pair
00028 #include <algorithm>                       // for std::max
00029 
00030 
00031 BDSMagnetOuterFactoryCylindrical* BDSMagnetOuterFactoryCylindrical::_instance = 0;
00032 
00033 BDSMagnetOuterFactoryCylindrical* BDSMagnetOuterFactoryCylindrical::Instance()
00034 {
00035   if (_instance == 0)
00036     {_instance = new BDSMagnetOuterFactoryCylindrical();}
00037   return _instance;
00038 }
00039 
00040 BDSMagnetOuterFactoryCylindrical::BDSMagnetOuterFactoryCylindrical()
00041 {;}
00042 
00043 BDSMagnetOuterFactoryCylindrical::~BDSMagnetOuterFactoryCylindrical()
00044 {
00045   _instance = 0;
00046 }
00047 
00048 BDSGeometryComponent* BDSMagnetOuterFactoryCylindrical::CreateSectorBend(G4String      name,
00049                                                                          G4double      length,
00050                                                                          BDSBeamPipe*  beamPipe,
00051                                                                          G4double      boxSize,
00052                                                                          G4double      angle,
00053                                                                          G4Material*   outerMaterial)
00054 {
00055 #ifdef BDSDEBUG
00056   G4cout << __METHOD_NAME__ << G4endl;
00057 #endif
00058   // clear up variables
00059   CleanUp();
00060   
00061   // test input parameters - set global options as default if not specified
00062   TestInputParameters(beamPipe,boxSize,outerMaterial);
00063 
00064   G4int orientation   = BDS::CalculateOrientation(angle);
00065   G4double zcomponent = cos(fabs(angle*0.5)); // calculate components of normal vectors (in the end mag(normal) = 1)
00066   G4double xcomponent = sin(fabs(angle*0.5)); // note full angle here as it's the exit angle
00067   G4ThreeVector inputface  = G4ThreeVector(-orientation*xcomponent, 0.0, -1.0*zcomponent); //-1 as pointing down in z for normal
00068   G4ThreeVector outputface = G4ThreeVector(-orientation*xcomponent, 0.0, zcomponent);   // no output face angle
00069   
00070   if (beamPipe->ContainerIsCircular())
00071     {
00072       //circular beampipe so we can simply use its radius
00073       yokeSolid = new G4CutTubs(name + "_yoke_solid",       // name
00074                                 beamPipe->GetContainerRadius() + 2*lengthSafety,  // inner radius
00075                                 boxSize*0.5,                 // outer radius
00076                                 length*0.5-2*lengthSafety,   // half length
00077                                 0,                           // rotation start angle
00078                                 CLHEP::twopi,                // rotation finish angle
00079                                 inputface,                   // input face normal
00080                                 outputface);                 // output face normal
00081 
00082       //container is similar but slightly wider and hollow (to allow placement of beampipe)
00083       containerSolid = new G4CutTubs(name + "_contiainer_solid",  // name
00084                                      beamPipe->GetContainerRadius() + lengthSafety, // inner radius
00085                                      boxSize*0.5 + lengthSafety,  // outer radius
00086                                      length*0.5,                  // half length
00087                                      0,                           // rotation start angle
00088                                      CLHEP::twopi,                // rotation finish angle
00089                                      inputface,                   // input face normal
00090                                      outputface);                 // output face normal
00091     }
00092   else
00093     {
00094       G4VSolid* yokeSolidCylinder = new G4CutTubs(name + "_yoke_solid_cylinder",  // name
00095                                                   0,  // inner radius - for unambiguous subtraction
00096                                                   boxSize*0.5,                 // outer radius
00097                                                   length*0.5-2*lengthSafety,   // half length
00098                                                   0,                           // rotation start angle
00099                                                   CLHEP::twopi,                // rotation finish angle
00100                                                   inputface,                   // input face normal
00101                                                   outputface);                 // output face normal
00102       yokeSolid = new G4SubtractionSolid(name + "_yoke_solid",
00103                                           yokeSolidCylinder,
00104                                           beamPipe->GetContainerSubtractionSolid());
00105 
00106       //container is similar but slightly wider
00107       G4VSolid* containerSolidCylinder = new G4CutTubs(name + "_container_solid_cylinder", // name
00108                                                        0,  // inner radius - for unambiguous subtraction
00109                                                        boxSize*0.5 + lengthSafety,  // outer radius
00110                                                        length*0.5,                  // half length
00111                                                        0,                           // rotation start angle
00112                                                        CLHEP::twopi,                // rotation finish angle
00113                                                        inputface,                   // input face normal
00114                                                        outputface);                 // output face normal
00115       containerSolid = new G4SubtractionSolid(name + "_container_solid",
00116                                               containerSolidCylinder,
00117                                               beamPipe->GetContainerSubtractionSolid());
00118     }
00119   return CommonFinalConstructor(name,length,boxSize,outerMaterial,BDSMagnetColours::Instance()->GetMagnetColour("sectorbend"));
00120 }
00121 
00122 BDSGeometryComponent* BDSMagnetOuterFactoryCylindrical::CreateRectangularBend(G4String      name,
00123                                                                               G4double      length,
00124                                                                               BDSBeamPipe*  beamPipe,
00125                                                                               G4double      boxSize,
00126                                                                               G4double      /*angle*/,
00127                                                                               G4Material*   outerMaterial)
00128 {
00129 #ifdef BDSDEBUG
00130   G4cout << __METHOD_NAME__ << G4endl;
00131 #endif  
00132   //rectangular bends currently just make a shorter straight volume, so ignore angle for now
00133   CreateCylindricalSolids(name, length, beamPipe, boxSize);
00134   return CommonFinalConstructor(name, length, boxSize, outerMaterial, BDSMagnetColours::Instance()->GetMagnetColour("rectangularbend"));
00135 }
00136 
00137 BDSGeometryComponent* BDSMagnetOuterFactoryCylindrical::CreateQuadrupole(G4String      name,
00138                                                                          G4double      length,
00139                                                                          BDSBeamPipe*  beamPipe,
00140                                                                          G4double      boxSize,
00141                                                                          G4Material*   outerMaterial)
00142 {
00143 #ifdef BDSDEBUG
00144   G4cout << __METHOD_NAME__ << G4endl;
00145 #endif
00146   CreateCylindricalSolids(name, length, beamPipe, boxSize);
00147   return CommonFinalConstructor(name, length, boxSize, outerMaterial, BDSMagnetColours::Instance()->GetMagnetColour("quadrupole"));
00148 }
00149 
00150 BDSGeometryComponent* BDSMagnetOuterFactoryCylindrical::CreateSextupole(G4String      name,
00151                                                                         G4double      length,
00152                                                                         BDSBeamPipe*  beamPipe,
00153                                                                         G4double      boxSize,
00154                                                                         G4Material*   outerMaterial)
00155 {
00156   CreateCylindricalSolids(name, length, beamPipe, boxSize);
00157   return CommonFinalConstructor(name, length, boxSize, outerMaterial, BDSMagnetColours::Instance()->GetMagnetColour("sextupole"));
00158 }
00159 
00160 BDSGeometryComponent* BDSMagnetOuterFactoryCylindrical::CreateOctupole(G4String      name,
00161                                                                        G4double      length,
00162                                                                        BDSBeamPipe*  beamPipe,
00163                                                                        G4double      boxSize,
00164                                                                        G4Material*   outerMaterial)
00165 {
00166 #ifdef BDSDEBUG
00167   G4cout << __METHOD_NAME__ << G4endl;
00168 #endif
00169   CreateCylindricalSolids(name, length, beamPipe, boxSize);
00170   return CommonFinalConstructor(name, length, boxSize, outerMaterial, BDSMagnetColours::Instance()->GetMagnetColour("octupole"));
00171 }
00172 
00173 BDSGeometryComponent* BDSMagnetOuterFactoryCylindrical::CreateDecapole(G4String      name,
00174                                                                        G4double      length,
00175                                                                        BDSBeamPipe*  beamPipe,
00176                                                                        G4double      boxSize,
00177                                                                        G4Material*   outerMaterial)
00178 {
00179 #ifdef BDSDEBUG
00180   G4cout << __METHOD_NAME__ << G4endl;
00181 #endif
00182   CreateCylindricalSolids(name, length, beamPipe, boxSize);
00183   return CommonFinalConstructor(name, length, boxSize, outerMaterial, BDSMagnetColours::Instance()->GetMagnetColour("decapole"));
00184 }
00185 
00186 BDSGeometryComponent* BDSMagnetOuterFactoryCylindrical::CreateSolenoid(G4String      name,
00187                                                                        G4double      length,
00188                                                                        BDSBeamPipe*  beamPipe,
00189                                                                        G4double      boxSize,
00190                                                                        G4Material*   outerMaterial)
00191 {
00192   CreateCylindricalSolids(name, length, beamPipe, boxSize);
00193   return CommonFinalConstructor(name, length, boxSize, outerMaterial, BDSMagnetColours::Instance()->GetMagnetColour("solenoid"));
00194 }
00195 
00196 BDSGeometryComponent* BDSMagnetOuterFactoryCylindrical::CreateMultipole(G4String      name,
00197                                                                         G4double      length,
00198                                                                         BDSBeamPipe*  beamPipe,
00199                                                                         G4double      boxSize,
00200                                                                         G4Material*   outerMaterial)
00201 {
00202 #ifdef BDSDEBUG
00203   G4cout << __METHOD_NAME__ << G4endl;
00204 #endif
00205   CreateCylindricalSolids(name, length, beamPipe, boxSize);
00206   return CommonFinalConstructor(name, length, boxSize, outerMaterial, BDSMagnetColours::Instance()->GetMagnetColour("multipole"));
00207 }
00208 
00209 BDSGeometryComponent* BDSMagnetOuterFactoryCylindrical::CreateRfCavity(G4String      name,
00210                                                                        G4double      length,
00211                                                                        BDSBeamPipe*  beamPipe,
00212                                                                        G4double      boxSize,
00213                                                                        G4Material*   outerMaterial)
00214 {
00215 #ifdef BDSDEBUG
00216   G4cout << __METHOD_NAME__ << G4endl;
00217 #endif
00218   CreateCylindricalSolids(name, length, beamPipe, boxSize);
00219   return CommonFinalConstructor(name, length, boxSize, outerMaterial, BDSMagnetColours::Instance()->GetMagnetColour("rfcavity"));
00220 }
00221 
00222 BDSGeometryComponent* BDSMagnetOuterFactoryCylindrical::CreateMuSpoiler(G4String      name,
00223                                                                        G4double      length,
00224                                                                        BDSBeamPipe*  beamPipe,
00225                                                                        G4double      boxSize,
00226                                                                        G4Material*   outerMaterial)
00227 {
00228 #ifdef BDSDEBUG
00229   G4cout << __METHOD_NAME__ << G4endl;
00230 #endif
00231   CreateCylindricalSolids(name, length, beamPipe, boxSize);
00232   return CommonFinalConstructor(name, length, boxSize, outerMaterial, BDSMagnetColours::Instance()->GetMagnetColour("muspoiler"));
00233 }
00234 
00235 BDSGeometryComponent* BDSMagnetOuterFactoryCylindrical::CreateKicker(G4String      name,
00236                                                                      G4double      length,
00237                                                                      BDSBeamPipe*  beamPipe,
00238                                                                      G4double      boxSize,
00239                                                                      G4bool        /*vertical*/,
00240                                                                      G4Material*   outerMaterial)
00241 {
00242 #ifdef BDSDEBUG
00243   G4cout << __METHOD_NAME__ << G4endl;
00244 #endif
00245   // in this factory, h and v kickers will look the same so ignore bool vertical
00246   // have to retain it though for virtual base class compatability
00247   CreateCylindricalSolids(name, length, beamPipe, boxSize);
00248   return CommonFinalConstructor(name, length, boxSize, outerMaterial, BDSMagnetColours::Instance()->GetMagnetColour("hkicker"));
00249 }
00250 
00252 
00253 void BDSMagnetOuterFactoryCylindrical::CreateCylindricalSolids(G4String     name,
00254                                                                G4double     length,
00255                                                                BDSBeamPipe* beamPipe,
00256                                                                G4double     boxSize)
00257 {
00258   // clear up variables
00259   CleanUp();
00260   
00261   if (beamPipe->ContainerIsCircular())
00262     {
00263       //circular beampipe so we can simply use its radius
00264       yokeSolid = new G4Tubs(name + "_yoke_solid",       // name
00265                              beamPipe->GetContainerRadius() + 2*lengthSafety,  // inner radius
00266                              boxSize*0.5,                 // outer radius
00267                              length*0.5-2*lengthSafety,   // half length
00268                              0,                           // rotation start angle
00269                              CLHEP::twopi);               // rotation finish angle
00270 
00271       //container is similar but slightly wider and hollow (to allow placement of beampipe)
00272       containerSolid = new G4Tubs(name + "_contiainer_solid",  // name
00273                                   beamPipe->GetContainerRadius() + lengthSafety, // inner radius
00274                                   boxSize*0.5 + lengthSafety,  // outer radius
00275                                   length*0.5,                  // half length
00276                                   0,                           // rotation start angle
00277                                   CLHEP::twopi);               // rotation finish angle
00278     }
00279   else
00280     {
00281       G4VSolid* yokeSolidCylinder = new G4Tubs(name + "_yoke_solid_cylinder",  // name
00282                                                0,  // inner radius - for unambiguous subtraction
00283                                                boxSize*0.5,                 // outer radius
00284                                                length*0.5-2*lengthSafety,   // half length
00285                                                0,                           // rotation start angle
00286                                                CLHEP::twopi);               // rotation finish angle
00287       yokeSolid = new G4SubtractionSolid(name + "_yoke_solid",
00288                                          yokeSolidCylinder,
00289                                          beamPipe->GetContainerSubtractionSolid());
00290 
00291       //container is similar but slightly wider
00292       G4VSolid* containerSolidCylinder = new G4Tubs(name + "_container_solid_cylinder", // name
00293                                                     0,  // inner radius - for unambiguous subtraction
00294                                                     boxSize*0.5 + lengthSafety,  // outer radius
00295                                                     length*0.5,                  // half length
00296                                                     0,                           // rotation start angle
00297                                                     CLHEP::twopi);               // rotation finish angle
00298       containerSolid = new G4SubtractionSolid(name + "_container_solid",
00299                                               containerSolidCylinder,
00300                                               beamPipe->GetContainerSubtractionSolid());
00301     }
00302 }
00303 
00304 void BDSMagnetOuterFactoryCylindrical::TestInputParameters(BDSBeamPipe* beamPipe,
00305                                                            G4double&    boxSize,
00306                                                            G4Material*& outerMaterial)// reference to a pointer
00307 {
00308   //function arguments by reference to they can be modified in place
00309   //check outer material is something
00310   if (!outerMaterial)
00311     {outerMaterial = BDSMaterials::Instance()->GetMaterial(BDSGlobalConstants::Instance()->GetEmptyMaterial());}
00312 
00313   // ensure box size is bigger than the beampipe
00314   if (beamPipe->ContainerIsCircular()) {
00315     // if it's circular, just check radius
00316     if (boxSize < 2*(beamPipe->GetContainerRadius()) )
00317       {boxSize = 2*(beamPipe->GetContainerRadius()) + 1*CLHEP::mm;}
00318   } else {
00319     // it's not circular - have a look at extents
00320     // +ve - -ve
00321     G4double extentX = beamPipe->GetExtentX().second - beamPipe->GetExtentX().first;
00322     G4double extentY = beamPipe->GetExtentY().second - beamPipe->GetExtentY().first;
00323     if ( (boxSize < extentX) || (boxSize < extentY) ) {
00324       // boxSize isn't sufficient for range in x or y
00325       boxSize = std::max(extentX,extentY) + 1*CLHEP::mm;
00326     }
00327   }
00328     
00329 }
00330 
00333 BDSGeometryComponent* BDSMagnetOuterFactoryCylindrical::CommonFinalConstructor(G4String    name,
00334                                                                                G4double    length,
00335                                                                                G4double    boxSize,
00336                                                                                G4Material* outerMaterial,
00337                                                                                G4Colour*   colour)
00338 {
00339 #ifdef BDSDEBUG
00340   G4cout << __METHOD_NAME__ << G4endl;
00341 #endif
00342   
00343   // build the logical volumes
00344   G4LogicalVolume* yokeLV   = new G4LogicalVolume(yokeSolid,
00345                                                   outerMaterial,
00346                                                   name + "_yoke_lv");
00347 
00348   G4Material* emptyMaterial = BDSMaterials::Instance()->GetMaterial(BDSGlobalConstants::Instance()->GetEmptyMaterial());
00349   G4LogicalVolume* containerLV = new G4LogicalVolume(containerSolid,
00350                                                      emptyMaterial,
00351                                                      name + "_container_lv");
00352   
00353   // VISUAL ATTRIBUTES
00354   // set visual attributes
00355   // outer
00356   G4VisAttributes* outerVisAttr = new G4VisAttributes(*colour);
00357   outerVisAttr->SetVisibility(true);
00358   outerVisAttr->SetForceLineSegmentsPerCircle(nSegmentsPerCircle);
00359   yokeLV->SetVisAttributes(outerVisAttr);
00360   // container
00361   if (BDSExecOptions::Instance()->GetVisDebug())
00362     {containerLV->SetVisAttributes(BDSGlobalConstants::Instance()->GetVisibleDebugVisAttr());}
00363   else
00364     {containerLV->SetVisAttributes(BDSGlobalConstants::Instance()->GetInvisibleVisAttr());}
00365 
00366   // USER LIMITS - set user limits based on bdsim user specified parameters
00367 #ifndef NOUSERLIMITS
00368   G4UserLimits* outerUserLimits = new G4UserLimits("outer_cuts");
00369   outerUserLimits->SetMaxAllowedStep( length * maxStepFactor );
00370   outerUserLimits->SetUserMinEkine(BDSGlobalConstants::Instance()->GetThresholdCutCharged());
00371   outerUserLimits->SetUserMaxTime(BDSGlobalConstants::Instance()->GetMaxTime());
00372   //attach cuts to volumes
00373   yokeLV->SetUserLimits(outerUserLimits);
00374   containerLV->SetUserLimits(outerUserLimits);
00375 #endif
00376 
00377   // PLACEMENT
00378   // place the components inside the container
00379   // note we don't need the pointer for anything - it's registered upon construction with g4
00380   new G4PVPlacement((G4RotationMatrix*)0,         // no rotation
00381                     (G4ThreeVector)0,             // position
00382                     yokeLV,                       // lv to be placed
00383                     name + "_yoke_pv",            // name
00384                     containerLV,                  // mother lv to be place in
00385                     false,                        // no boolean operation
00386                     0,                            // copy number
00387                     checkOverlaps); // whether to check overlaps
00388 
00389   // record extents
00390   // container radius is the same for all methods as all cylindrical
00391   G4double containerRadius = boxSize + lengthSafety;
00392   std::pair<double,double> extX = std::make_pair(-containerRadius,containerRadius);
00393   std::pair<double,double> extY = std::make_pair(-containerRadius,containerRadius);
00394   std::pair<double,double> extZ = std::make_pair(-length*0.5,length*0.5);
00395   
00396   // build the BDSGeometryComponent instance and return it
00397   BDSGeometryComponent* outer = new BDSGeometryComponent(containerSolid,
00398                                                          containerLV,
00399                                                          extX, extY, extZ);
00400   // REGISTER all lvs
00401   outer->RegisterLogicalVolume(yokeLV); //using geometry component base class method
00402 
00403   // sensitive volumes
00404   outer->RegisterSensitiveVolume(yokeLV);
00405   
00406   return outer;
00407 }

Generated on 28 Jun 2015 for BDSIM by  doxygen 1.4.7