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