/home/cern/BDSIM_new/src/BDSMultipole.cc

00001 /* BDSIM code.    Version 1.0
00002    Author: Grahame A. Blair, Royal Holloway, Univ. of London.
00003    Last modified 24.7.2002
00004    Copyright (c) 2002 by G.A.Blair.  ALL RIGHTS RESERVED. 
00005 
00006    Modified 22.03.05 by J.C.Carter, Royal Holloway, Univ. of London.
00007    Added extra parameter to BuildDefaultOuterLogicalVolume so that it is 
00008      possible to set the material as either Iron or Vacuum
00009    Removed StringFromInt function
00010 */
00011 #include "BDSGlobalConstants.hh" // must be first in include list
00012 
00013 #include <cstdlib>
00014 
00015 #include "BDSMultipole.hh"
00016 #include "G4Box.hh"
00017 #include "G4Tubs.hh"
00018 #include "G4VisAttributes.hh"
00019 #include "G4LogicalVolume.hh"
00020 #include "G4VPhysicalVolume.hh"
00021 #include "G4UserLimits.hh"
00022 #include "G4TransportationManager.hh"
00023 
00024 #include "G4MagIntegratorStepper.hh"
00025 
00026 #include "BDSMultipoleOuterMagField.hh"
00027 #include "G4MagneticField.hh"
00028 
00029 #include <map>
00030 #include <string>
00031 
00032 
00033 const int DEBUG= 0;
00034 
00035 //============================================================
00036 
00037 typedef std::map<G4String,int> LogVolCountMap;
00038 extern LogVolCountMap* LogVolCount;
00039 
00040 typedef std::map<G4String,G4LogicalVolume*> LogVolMap;
00041 extern LogVolMap* LogVol;
00042 
00043 extern BDSMaterials* theMaterials;
00044 extern G4RotationMatrix* RotY90;
00045 
00046 //============================================================
00047 
00048 BDSMultipole::BDSMultipole( G4String aName, 
00049                             G4double aLength,
00050                             G4double aBpRadius,
00051                             G4double aInnerIronRadius,
00052                             G4VisAttributes* aVisAtt,
00053                             G4String aMaterial,
00054                             G4double aXAper,
00055                             G4double aYAper,
00056                             G4double angle):
00057   BDSAcceleratorComponent(
00058                          aName, 
00059                          aLength,
00060                          aBpRadius,
00061                          aXAper,
00062                          aYAper,
00063                          aVisAtt,
00064                          aMaterial,
00065                          angle),
00066   itsInnerIronRadius(aInnerIronRadius)
00067 {}
00068 
00069 
00070 void BDSMultipole::BuildBeampipe(G4double aLength,
00071                                  G4String materialName,
00072                                  G4int nSegments)
00073 {
00074 
00075   itsNSegments=nSegments;
00076   G4double dSegments=double(nSegments);
00077 
00078   G4Material *material;
00079 
00080   if(materialName == "")
00081     {
00082       material = theMaterials->GetMaterial( BDSGlobals->GetPipeMaterialName() );
00083     }
00084   else
00085     {
00086       material = theMaterials->GetMaterial(materialName);
00087     }
00088 
00089   // build beampipe
00090 
00091   if(DEBUG) G4cout << "Outer pipe :"
00092                    << " r= " << itsBpRadius/m << " m"
00093                    << " l= " << aLength/(2.*dSegments)/m << " m"
00094                    << G4endl;
00095 
00096   itsBPTube=new G4Tubs(itsName+"_bmp_solid",
00097                        itsBpRadius-BDSGlobals->GetBeampipeThickness(),
00098                        itsBpRadius,
00099                        aLength/(2.*dSegments),
00100                        0,twopi*radian);
00101 
00102   if(DEBUG) G4cout << "Inner pipe :"
00103                    << " r= " << (itsBpRadius-BDSGlobals->GetBeampipeThickness() )/m
00104                    << " m"
00105                    << " l= " << aLength/(2.*dSegments)/m << " m"
00106                    << G4endl;
00107   
00108   if(nSegments==1)
00109     {
00110       itsInnerBPTube=new G4Tubs(itsName+"_inner_bmp_solid",
00111                                 0.,
00112                                 itsBpRadius-BDSGlobals->GetBeampipeThickness(),
00113                                 aLength/2,
00114                                 0,twopi*radian);
00115     }
00116   else
00117     {
00118       itsInnerBPTube=new G4Tubs(itsName+"_inner_bmp_solid",
00119                                 0.,
00120                                 itsBpRadius-BDSGlobals->GetBeampipeThickness(),
00121                                 aLength/(2.*dSegments)-
00122                                   itsBpRadius*tan(itsAngle/(2.*dSegments)),
00123                                 0,twopi*radian); 
00124     }
00125 
00126   itsBeampipeLogicalVolume=     
00127     new G4LogicalVolume(itsBPTube,
00128                         material,
00129                         itsName+"_bmp_log");
00130 
00131   itsInnerBPLogicalVolume=      
00132     new G4LogicalVolume(itsInnerBPTube,
00133                         theMaterials->GetMaterial("Vacuum"),
00134                         itsName+"_inner_bmp_log");
00135   
00136   G4VPhysicalVolume* PhysiInner;
00137   PhysiInner = new G4PVPlacement(
00138                       0,                        // rotation
00139                       0,                        // at (0,0,0)
00140                       itsInnerBPLogicalVolume,  // its logical volume
00141                       itsName+"_inner_bmp_phys",// its name
00142                       itsMarkerLogicalVolume,   // its mother  volume
00143                       false,                    // no boolean operation
00144                       0);                       // copy number
00145     
00146   if(nSegments==1)
00147     {
00148       G4RotationMatrix* Rot=NULL;
00149       if(itsAngle!=0 && itsType!="rbend") Rot=RotY90;  
00150       // doesn't apply to rbends 
00151       // this is needed because sbends are rendered as trapezoids G4Trd,
00152       // rotated by 90 degrees???
00153       
00154       G4VPhysicalVolume* PhysiComp;
00155       PhysiComp = new G4PVPlacement(
00156                           Rot,                       // rotation
00157                           0,                         // at (0,0,0)
00158                           itsBeampipeLogicalVolume,  // its logical volume
00159                           itsName+"_bmp_phys",       // its name
00160                           itsMarkerLogicalVolume,    // its mother  volume
00161                           false,                     // no boolean operation
00162                           0);                        // copy number
00163     }
00164   else
00165     {
00166       itsSegRot=new G4RotationMatrix();
00167       G4double DeltaRot=fabs(itsAngle)/(double(nSegments));
00168       
00169       G4double angle=- fabs(itsAngle/2)-DeltaRot/2.;
00170       itsSegRot->rotateY(acos(0.) + angle );
00171       
00172       G4double X,Y,Z,R,Z0;
00173       
00174       R=itsLength/fabs(itsAngle);
00175       Z0=R*(1.-cos(fabs(itsAngle/2)-DeltaRot/2.));
00176       
00177       // loop:
00178       for(G4int iSeg=0;iSeg<nSegments;iSeg++)
00179         {
00180           itsSegRot->rotateY(DeltaRot);
00181           angle+=DeltaRot;
00182 
00183 
00184           X=R*sin(angle);
00185           Y=0.;
00186           Z=R*(1.-cos(angle))-Z0;
00187           
00188 
00189 
00190           itsSegPos.setX(X);
00191           itsSegPos.setY(Y);
00192           itsSegPos.setZ(Z);
00193 
00194           G4VPhysicalVolume* PhysiComp;
00195           PhysiComp = new G4PVPlacement(
00196                               itsSegRot,                // rotation
00197                               itsSegPos,                // at (0,0,0)
00198                               itsBeampipeLogicalVolume, // its logical volume
00199                               itsName+"_bmp_phys",      // its name
00200                               itsMarkerLogicalVolume,   // its mother  volume
00201                               false,                    // no boolean operation
00202                               0);                       // copy number
00203         }
00204     }
00205 
00206 
00207   itsBeampipeUserLimits =
00208      new G4UserLimits("beampipe cuts",DBL_MAX,DBL_MAX,DBL_MAX,
00209                      BDSGlobals->GetThresholdCutCharged());
00210 
00211   itsInnerBeampipeUserLimits =
00212     new G4UserLimits("inner beampipe cuts",DBL_MAX,DBL_MAX,DBL_MAX,
00213                      BDSGlobals->GetThresholdCutCharged());
00214 
00215   itsBeampipeUserLimits->SetMaxAllowedStep(aLength);
00216   itsBeampipeLogicalVolume->SetUserLimits(itsBeampipeUserLimits);
00217 
00218   itsInnerBeampipeUserLimits->SetMaxAllowedStep(aLength);
00219   itsInnerBPLogicalVolume->SetUserLimits(itsInnerBeampipeUserLimits);
00220 
00221   itsBeampipeLogicalVolume->SetFieldManager(BDSGlobals->GetZeroFieldManager(),false);
00222   itsInnerBPLogicalVolume->SetFieldManager(itsBPFieldMgr,false) ;
00223 
00224   // now protect the fields inside the marker volume by giving the
00225   // marker a null magnetic field (otherwise G4VPlacement can
00226   // over-ride the already-created fields, by calling 
00227   // G4LogicalVolume::AddDaughter, which calls 
00228   // pDaughterLogical->SetFieldManager(fFieldManager, true) - the
00229   // latter 'true' over-writes all the other fields
00230 
00231   itsMarkerLogicalVolume->
00232     SetFieldManager(BDSGlobals->GetZeroFieldManager(),false);
00233   
00234   //
00235   // set visualization attributes
00236   //
00237   G4VisAttributes* VisAtt =  new G4VisAttributes(G4Colour(0., 0., 0));
00238   VisAtt->SetForceSolid(true);
00239   itsInnerBPLogicalVolume->SetVisAttributes(VisAtt);
00240 
00241   G4VisAttributes* VisAtt1 = new G4VisAttributes(G4Colour(0.4, 0.4, 0.4));
00242   VisAtt1->SetForceSolid(true);
00243   itsBeampipeLogicalVolume->SetVisAttributes(VisAtt1);
00244 }
00245 
00246 
00247 void BDSMultipole::BuildBPFieldMgr(G4MagIntegratorStepper* aStepper,
00248                                    G4MagneticField* aField)
00249 {
00250   itsChordFinder= 
00251     new G4ChordFinder(aField,
00252                       BDSGlobals->GetChordStepMinimum(),
00253                       aStepper);
00254 
00255   itsChordFinder->SetDeltaChord(BDSGlobals->GetDeltaChord());
00256 
00257   itsBPFieldMgr= new G4FieldManager();
00258   itsBPFieldMgr->SetDetectorField(aField);
00259   itsBPFieldMgr->SetChordFinder(itsChordFinder);
00260   itsBPFieldMgr->SetDeltaIntersection(BDSGlobals->GetDeltaIntersection());
00261   
00262   if(BDSGlobals->GetMinimumEpsilonStep()>0)
00263     itsBPFieldMgr->SetMinimumEpsilonStep(BDSGlobals->GetMinimumEpsilonStep());
00264 
00265   if(BDSGlobals->GetMaximumEpsilonStep()>0)
00266     itsBPFieldMgr->SetMaximumEpsilonStep(BDSGlobals->GetMaximumEpsilonStep());
00267 
00268   if(BDSGlobals->GetDeltaOneStep()>0)
00269     itsBPFieldMgr->SetDeltaOneStep(BDSGlobals->GetDeltaOneStep());
00270   
00271 }
00272 
00273 
00274 void BDSMultipole::BuildDefaultMarkerLogicalVolume()
00275 {
00276   G4double xLength, yLength;
00277   xLength = yLength = std::max(itsOuterR,BDSGlobals->GetComponentBoxSize()/2);
00278 
00279   if(DEBUG) G4cout<<"marker volume : x/y="<<xLength/m<<
00280               " m, l= "<<  (itsLength+BDSGlobals->GetLengthSafety())/2/m <<" m"<<G4endl;
00281 
00282   itsMarkerLogicalVolume=new G4LogicalVolume
00283     (new G4Box( itsName+"_solid",
00284                 xLength,
00285                 yLength,
00286                 (itsLength+BDSGlobals->GetLengthSafety())/2), //z half length 
00287      theMaterials->GetMaterial("Vacuum"),
00288      itsName+"_log");
00289 
00290   // itsMarkerUserLimits =
00291   //   new G4UserLimits(DBL_MAX,DBL_MAX,DBL_MAX,
00292   //                 BDSGlobals->GetThresholdCutCharged());     
00293   // itsMarkerUserLimits->SetMaxAllowedStep(itsLength);
00294   // itsMarkerLogicalVolume->SetUserLimits(itsMarkerUserLimits);
00295 
00296 }
00297 
00298 
00299 void BDSMultipole::BuildDefaultOuterLogicalVolume(G4double aLength,
00300                                                   G4bool OuterMaterialIsVacuum)
00301 {
00302   //OuterMaterialIsVacuum parameter is useless: one can set
00303   //itsMaterial = "Vacuum" and obtain the same result. Or cannot?
00304 
00305   // compute sagitta:
00306   G4double sagitta=0.;
00307 
00308   G4Material* material;
00309   if(itsMaterial != "") material = theMaterials->GetMaterial(itsMaterial);
00310   else material = theMaterials->GetMaterial("Iron");
00311 
00312   G4double outerRadius = itsOuterR;
00313   if(itsOuterR==0) outerRadius = BDSGlobals->GetComponentBoxSize()/2;
00314 
00315   if(itsNSegments>1)
00316     {
00317       sagitta=itsLength/itsAngle*(1.-cos(itsAngle/2.));
00318     }
00319   if(OuterMaterialIsVacuum)
00320     {
00321       itsOuterLogicalVolume=
00322         new G4LogicalVolume(new G4Tubs(itsName+"_outer_solid",
00323                                        itsInnerIronRadius+sagitta,
00324                                        outerRadius,
00325                                        aLength/2,
00326                                        0,twopi*radian),
00327                             theMaterials->GetMaterial("Vacuum"),
00328                             itsName+"_outer_log");
00329     }
00330   if(!OuterMaterialIsVacuum)
00331     {
00332       itsOuterLogicalVolume=
00333         new G4LogicalVolume(new G4Tubs(itsName+"_outer_solid",
00334                                        itsInnerIronRadius+sagitta,
00335                                        outerRadius,
00336                                        aLength/2,
00337                                        0,twopi*radian),
00338                             material,
00339                             itsName+"_outer_log");
00340     }
00341   
00342   G4RotationMatrix* Rot=NULL;
00343   if(itsAngle!=0 && itsType!="rbend") Rot=RotY90;
00344   
00345   itsPhysiComp = new G4PVPlacement(
00346                       Rot,                    // its rotation
00347                       0,                      // its position
00348                       itsOuterLogicalVolume,  // its logical volume
00349                       itsName+"_outer_phys",  // its name
00350                       itsMarkerLogicalVolume, // its mother  volume
00351                       false,                  // no boolean operation
00352                       0);                     // copy number
00353 
00354   itsOuterUserLimits =
00355     new G4UserLimits("multipole cut",aLength,DBL_MAX,DBL_MAX,
00356                      BDSGlobals->GetThresholdCutCharged());
00357   //  itsOuterUserLimits->SetMaxAllowedStep(aLength);
00358   itsOuterLogicalVolume->SetUserLimits(itsOuterUserLimits);
00359 
00360  
00361 
00362 }
00363 
00364 void BDSMultipole::BuildOuterFieldManager(G4int nPoles, G4double poleField,
00365                                           G4double phiOffset)
00366 {
00367   if(nPoles<=0 || nPoles>10 || nPoles%2 !=0)
00368     G4Exception("BDSMultipole: Invalid number of poles");
00369   itsNPoles=nPoles;
00370   itsOuterFieldMgr=NULL;
00371   if (poleField==0) return;
00372 
00373   itsOuterMagField=new BDSMultipoleOuterMagField(nPoles,poleField,phiOffset);
00374 
00375   itsOuterFieldMgr=new G4FieldManager(itsOuterMagField);
00376 
00377   //  (*theOuterFieldMap)[itsOuterLogicalVolume->GetName()]=itsOuterMagField;
00378 
00379   itsOuterLogicalVolume->SetFieldManager(itsOuterFieldMgr,false);
00380 
00381 
00382 }
00383 
00384 
00385 BDSMultipole::~BDSMultipole()
00386 {
00387   if(itsPhysiComp) delete itsPhysiComp;
00388   if(itsBPFieldMgr) delete itsBPFieldMgr;
00389   if(itsBeampipeLogicalVolume) delete itsBeampipeLogicalVolume;
00390   if(itsBPTube) delete itsBPTube;
00391   if(itsChordFinder) delete itsChordFinder;
00392   if(itsOuterUserLimits) delete itsOuterUserLimits;
00393   if(itsBeampipeUserLimits) delete itsBeampipeUserLimits;
00394   if(itsOuterFieldMgr) delete itsOuterFieldMgr;
00395   if(itsOuterMagField) delete itsOuterMagField;
00396   if(itsSegRot)delete itsSegRot;
00397 }

Generated on Wed Mar 5 17:25:22 2008 for BDSIM by  doxygen 1.5.3