/home/cern/BDSIM_new/src/BDSSectorBend.cc

00001 #include "BDSGlobalConstants.hh" // must be first in include list
00002 
00003 #include "BDSSectorBend.hh"
00004 #include "G4Tubs.hh"
00005 #include "G4IntersectionSolid.hh"
00006 #include "G4VisAttributes.hh"
00007 #include "G4LogicalVolume.hh"
00008 #include "G4VPhysicalVolume.hh"
00009 #include "G4UserLimits.hh"
00010 #include "G4TransportationManager.hh"
00011 
00012 #include <map>
00013 
00014 const int DEBUG = 0;
00015 
00016 //============================================================
00017 
00018 typedef std::map<G4String,int> LogVolCountMap;
00019 extern LogVolCountMap* LogVolCount;
00020 
00021 typedef std::map<G4String,G4LogicalVolume*> LogVolMap;
00022 extern LogVolMap* LogVol;
00023 
00024 extern BDSMaterials* theMaterials;
00025 
00026 extern G4RotationMatrix* RotY90;
00027 extern G4RotationMatrix* RotYM90;
00028 
00029 //============================================================
00030 
00031 BDSSectorBend::BDSSectorBend(G4String aName, G4double aLength, 
00032                              G4double bpRad, G4double FeRad,
00033                              G4double bField, G4double angle, G4double outR,
00034                              G4double tilt, G4double bGrad, 
00035                              G4String aMaterial, G4int nSegments):
00036   BDSMultipole(aName, aLength, bpRad, FeRad, SetVisAttributes(), aMaterial,
00037                0, 0, angle)
00038 {
00039   SetOuterRadius(outR);
00040   itsTilt=tilt;
00041   itsBField=bField;
00042   itsBGrad=bGrad;
00043   itsType="sbend";
00044 
00045   if (!(*LogVolCount)[itsName])
00046     {
00047       //
00048       // build external volume
00049       // 
00050       BuildSBMarkerLogicalVolume();
00051 
00052       //
00053       // build beampipe (geometry + magnetic field)
00054       //
00055       BuildBPFieldAndStepper();
00056       BuildBPFieldMgr(itsStepper,itsMagField);
00057       BuildSBBeampipe();
00058 
00059       //
00060       // build magnet (geometry + magnetic field)
00061       //
00062       BuildSBOuterLogicalVolume();
00063       if(BDSGlobals->GetIncludeIronMagFields())
00064         {
00065           G4double polePos[4];
00066           G4double Bfield[3];
00067 
00068           //coordinate in GetFieldValue
00069           polePos[0]=0.;
00070           polePos[1]=BDSGlobals->GetMagnetPoleRadius();
00071           polePos[2]=0.;
00072           polePos[3]=-999.;//flag to use polePos rather than local track
00073 
00074           itsMagField->GetFieldValue(polePos,Bfield);
00075           G4double BFldIron=
00076             sqrt(Bfield[0]*Bfield[0]+Bfield[1]*Bfield[1])*
00077             BDSGlobals->GetMagnetPoleSize()/
00078             (BDSGlobals->GetComponentBoxSize()/2-
00079              BDSGlobals->GetMagnetPoleRadius());
00080 
00081           // Magnetic flux from a pole is divided in two directions
00082           BFldIron/=2.;
00083           
00084           BuildOuterFieldManager(2, BFldIron,pi/2);
00085         }
00086 
00087       //
00088       // define sensitive volumes for hit generation
00089       //
00090       SetMultipleSensitiveVolumes(itsBeampipeLogicalVolume);
00091       SetMultipleSensitiveVolumes(itsOuterLogicalVolume);
00092 
00093       //
00094       // set visualization attributes
00095       //
00096       itsVisAttributes=SetVisAttributes();
00097       itsVisAttributes->SetForceSolid(true);
00098       itsOuterLogicalVolume->SetVisAttributes(itsVisAttributes);
00099 
00100       //
00101       // append marker logical volume to volume map
00102       //
00103       (*LogVolCount)[itsName]=1;
00104       (*LogVol)[itsName]=itsMarkerLogicalVolume;
00105     }
00106   else
00107     {
00108       (*LogVolCount)[itsName]++;
00109       if(BDSGlobals->GetSynchRadOn()&& BDSGlobals->GetSynchRescale())
00110         {
00111           // with synchrotron radiation, the rescaled magnetic field
00112           // means elements with the same name must have different
00113           // logical volumes, because they have different fields
00114           itsName+=BDSGlobals->StringFromInt((*LogVolCount)[itsName]);
00115 
00116           //
00117           // build external volume
00118           // 
00119           BuildSBMarkerLogicalVolume();
00120           
00121           //
00122           // build beampipe (geometry + magnetic field)
00123           //
00124           BuildBPFieldAndStepper();
00125           BuildBPFieldMgr(itsStepper,itsMagField);
00126           BuildSBBeampipe();
00127 
00128           //
00129           // build magnet (geometry + magnetic field)
00130           //
00131           BuildSBOuterLogicalVolume();
00132           if(BDSGlobals->GetIncludeIronMagFields())
00133             {
00134               G4double polePos[4];
00135               G4double Bfield[3];
00136               
00137               //coordinate in GetFieldValue
00138               polePos[0]=0.;
00139               polePos[1]=BDSGlobals->GetMagnetPoleRadius();
00140               polePos[2]=0.;
00141               polePos[3]=-999.;//flag to use polePos rather than local track
00142               
00143               itsMagField->GetFieldValue(polePos,Bfield);
00144               G4double BFldIron=
00145                 sqrt(Bfield[0]*Bfield[0]+Bfield[1]*Bfield[1])*
00146                 BDSGlobals->GetMagnetPoleSize()/
00147                 (BDSGlobals->GetComponentBoxSize()/2-
00148                  BDSGlobals->GetMagnetPoleRadius());
00149               
00150               // Magnetic flux from a pole is divided in two directions
00151               BFldIron/=2.;
00152 
00153               BuildOuterFieldManager(2, BFldIron,pi/2);
00154             }
00155           //When is SynchRescale(factor) called?
00156           
00157           //
00158           // define sensitive volumes for hit generation
00159           //
00160           SetSensitiveVolume(itsBeampipeLogicalVolume);// for synchrotron
00161           //SetSensitiveVolume(itsOuterLogicalVolume);// for laserwire
00162 
00163           //
00164           // set visualization attributes
00165           //
00166           itsVisAttributes=SetVisAttributes();
00167           itsVisAttributes->SetForceSolid(true);
00168           itsOuterLogicalVolume->SetVisAttributes(itsVisAttributes);
00169 
00170           //
00171           // append marker logical volume to volume map
00172           //
00173           (*LogVol)[itsName]=itsMarkerLogicalVolume;
00174         }
00175       else
00176         {
00177           //
00178           // use already defined marker volume
00179           //
00180           itsMarkerLogicalVolume=(*LogVol)[itsName];
00181         }      
00182     }
00183 }
00184 
00185 void BDSSectorBend::SynchRescale(G4double factor)
00186 {
00187   // rescale B field and gradient by same factor
00188   itsStepper->SetBGrad(itsBGrad*factor);
00189   itsStepper->SetBField(-itsBField*factor);
00190   // note that there are no methods to set the BDSSBendMagField as this
00191   // class does not do anything with the BFields.
00192   // not true when I will use Geant4 propagation
00193   if(DEBUG) G4cout << "Sbend " << itsName << " has been scaled" << G4endl;
00194 }
00195 
00196 G4VisAttributes* BDSSectorBend::SetVisAttributes()
00197 {
00198   itsVisAttributes = new G4VisAttributes(G4Colour(0,0,1)); //blue
00199   return itsVisAttributes;
00200 }
00201 
00202 void BDSSectorBend::BuildBPFieldAndStepper()
00203 {
00204   // set up the magnetic field and stepper
00205   G4ThreeVector Bfield(0.,-itsBField,0.);
00206   itsMagField=new BDSSbendMagField(Bfield,itsLength,itsAngle);
00207 
00208   itsEqRhs=new G4Mag_UsualEqRhs(itsMagField);  
00209   
00210   itsStepper = new myQuadStepper(itsEqRhs); // note the - sign...
00211   itsStepper->SetBField(-itsBField);
00212   itsStepper->SetBGrad(itsBGrad);
00213 }
00214 
00215 void BDSSectorBend::BuildSBMarkerLogicalVolume()
00216 {
00217   if (markerSolidVolume==0) {
00218 
00219     G4double boxSize=BDSGlobals->GetComponentBoxSize();
00220 
00221     G4double xHalfLengthMinus = (itsLength/itsAngle)*sin(itsAngle/2)
00222       - fabs(cos(itsAngle/2))*boxSize*tan(itsAngle/2)/2
00223       + BDSGlobals->GetLengthSafety()/2;
00224     
00225     G4double xHalfLengthPlus = (itsLength/itsAngle)*sin(itsAngle/2)
00226       + fabs(cos(itsAngle/2))*boxSize*tan(itsAngle/2)/2
00227       + BDSGlobals->GetLengthSafety()/2;
00228 
00229     markerSolidVolume = new G4Trd(itsName+"_marker",
00230                                   xHalfLengthPlus,     // x hlf lgth at +z
00231                                   xHalfLengthMinus,    // x hlf lgth at -z
00232                                   boxSize/2,           // y hlf lgth at +z
00233                                   boxSize/2,           // y hlf lgth at -z
00234                                   fabs(cos(itsAngle/2))*boxSize/2);// z hlf lgth
00235   }
00236 
00237   G4String LocalLogicalName=itsName;
00238   
00239   itsMarkerLogicalVolume=    
00240     new G4LogicalVolume(markerSolidVolume,
00241                         theMaterials->GetMaterial("Vacuum"),
00242                         LocalLogicalName+"_marker");
00243 
00244   itsMarkerUserLimits = new G4UserLimits(DBL_MAX,DBL_MAX,DBL_MAX);
00245   itsMarkerUserLimits->SetMaxAllowedStep(itsLength);
00246   itsMarkerLogicalVolume->SetUserLimits(itsMarkerUserLimits);
00247 
00248   //
00249   // zero field in the marker volume
00250   //
00251   itsMarkerLogicalVolume->
00252     SetFieldManager(BDSGlobals->GetZeroFieldManager(),false);
00253 }
00254 
00255 
00256 // construct a beampipe for sector bend
00257 void BDSSectorBend::BuildSBBeampipe()
00258 {
00259   //
00260   // use default beampipe material
00261   //
00262   G4Material *material =  theMaterials->GetMaterial( BDSGlobals->GetPipeMaterialName());
00263   
00264   //
00265   // compute some geometrical parameters
00266   //
00267   G4double bpThickness = BDSGlobals->GetBeampipeThickness();
00268   G4double boxSize = BDSGlobals->GetComponentBoxSize();
00269 
00270   G4double xHalfLengthMinus =
00271     (itsLength/itsAngle)*sin(itsAngle/2)
00272     - fabs(cos(itsAngle/2)) * boxSize * tan(itsAngle/2)/2
00273     + BDSGlobals->GetLengthSafety()/2;
00274 
00275   G4double xHalfLengthPlus =
00276     (itsLength/itsAngle)*sin(itsAngle/2)
00277     + fabs(cos(itsAngle/2)) * boxSize * tan(itsAngle/2)/2
00278     + BDSGlobals->GetLengthSafety()/2;
00279 
00280   G4double tubLen = std::max(xHalfLengthPlus,xHalfLengthMinus);
00281 
00282   //
00283   // build beampipe
00284   //
00285   G4Tubs *pipeTubsEnv = new G4Tubs(itsName+"_pipe_outer_env",
00286                                    itsBpRadius-bpThickness, // inner R
00287                                    itsBpRadius,             // outer R
00288                                    tubLen,                  // length
00289                                    0,                       // starting phi
00290                                    twopi * rad );           // delta phi
00291   
00292   G4Tubs *pipeInnerEnv = new G4Tubs(itsName+"_pipe_inner_env",
00293                                     0,                       // inner R
00294                                     itsBpRadius-bpThickness, // outer R
00295                                     tubLen,                  // length
00296                                     0,                       // starting phi
00297                                     twopi * rad );           // delta phi
00298 
00299   G4IntersectionSolid *pipeTubs =
00300     new G4IntersectionSolid(itsName+"_pipe_outer",
00301                             pipeTubsEnv,
00302                             markerSolidVolume,
00303                             RotYM90,
00304                             0);
00305   
00306   G4IntersectionSolid *pipeInner =
00307     new G4IntersectionSolid(itsName+"_pipe_inner",
00308                             pipeInnerEnv, 
00309                             markerSolidVolume,
00310                             RotYM90,
00311                             0);
00312 
00313   itsBeampipeLogicalVolume=     
00314     new G4LogicalVolume(pipeTubs,
00315                         material,
00316                         itsName+"_bmp_logical");
00317   
00318   itsInnerBPLogicalVolume=      
00319     new G4LogicalVolume(pipeInner,
00320                         theMaterials->GetMaterial("Vacuum"),
00321                         itsName+"_bmp_Inner_log");
00322 
00323   G4VPhysicalVolume* PhysiInner;
00324   PhysiInner = 
00325     new G4PVPlacement(
00326                       RotY90,                  // rotation
00327                       0,                       // at (0,0,0)
00328                       itsInnerBPLogicalVolume, // its logical volume
00329                       itsName+"_InnerBmp",     // its name
00330                       itsMarkerLogicalVolume,  // its mother volume
00331                       false,                   // no booleanm operation
00332                       0,                       // copy number
00333               true);// true --> check for overlaps with existing volumes
00334   G4VPhysicalVolume* PhysiComp;
00335   PhysiComp =
00336     new G4PVPlacement(
00337                       RotY90,                   // rotation
00338                       0,                        // at (0,0,0)
00339                       itsBeampipeLogicalVolume, // its logical volume
00340                       itsName+"_bmp",           // its name
00341                       itsMarkerLogicalVolume,   // its mother volume
00342                       false,                    // no boolean operation
00343                       0,                        // copy number
00344               true);// true --> check for overlaps with existing volumes
00345   //
00346   // set user limits for stepping, tracking and propagation in B field
00347   //
00348   itsBeampipeUserLimits =
00349     new G4UserLimits("beampipe cuts",DBL_MAX,DBL_MAX,DBL_MAX,
00350                      BDSGlobals->GetThresholdCutCharged());
00351   itsBeampipeUserLimits->SetMaxAllowedStep(itsLength);
00352   itsBeampipeLogicalVolume->SetUserLimits(itsBeampipeUserLimits);
00353   
00354   itsInnerBeampipeUserLimits =
00355     new G4UserLimits("inner beampipe cuts",DBL_MAX,DBL_MAX,DBL_MAX,
00356                      BDSGlobals->GetThresholdCutCharged());
00357   itsInnerBeampipeUserLimits->SetMaxAllowedStep(itsLength);
00358   itsInnerBPLogicalVolume->SetUserLimits(itsInnerBeampipeUserLimits);
00359 
00360   //
00361   // set magnetic field inside beampipe
00362   //
00363   itsBeampipeLogicalVolume->SetFieldManager(BDSGlobals->GetZeroFieldManager(),false);
00364   itsInnerBPLogicalVolume->SetFieldManager(itsBPFieldMgr,false);
00365 
00366   //
00367   // set visualization attributes
00368   //
00369   G4VisAttributes* VisAtt =  new G4VisAttributes(G4Colour(0., 0., 0));
00370   VisAtt->SetForceSolid(true);
00371   itsInnerBPLogicalVolume->SetVisAttributes(VisAtt);
00372 
00373   G4VisAttributes* VisAtt1 = new G4VisAttributes(G4Colour(0.4, 0.4, 0.4));
00374   VisAtt1->SetForceSolid(true);
00375   itsBeampipeLogicalVolume->SetVisAttributes(VisAtt1);
00376 }
00377 
00378 void BDSSectorBend::BuildSBOuterLogicalVolume(G4bool OuterMaterialIsVacuum){
00379 
00380   G4Material* material;
00381   if(itsMaterial != "")
00382     material = theMaterials->GetMaterial(itsMaterial);
00383   else
00384     material = theMaterials->GetMaterial("Iron");
00385 
00386   G4double boxSize = BDSGlobals->GetComponentBoxSize();
00387  
00388   G4double xHalfLengthMinus = (itsLength/itsAngle)*sin(itsAngle/2)
00389     - fabs(cos(itsAngle/2)) * boxSize * tan(itsAngle/2)/2
00390     + BDSGlobals->GetLengthSafety()/2;
00391 
00392   G4double xHalfLengthPlus = (itsLength/itsAngle)*sin(itsAngle/2)
00393     + fabs(cos(itsAngle/2)) * boxSize * tan(itsAngle/2)/2
00394     + BDSGlobals->GetLengthSafety()/2;
00395 
00396   G4double tubLen = std::max(xHalfLengthPlus,xHalfLengthMinus);
00397   
00398   G4Tubs *magTubsEnv =
00399     new G4Tubs(itsName+"_solid_env",
00400                itsInnerIronRadius, // inner R
00401                itsOuterR,          // outer R
00402                tubLen,             // length
00403                0,                  // starting phi
00404                twopi * rad );      // delta phi
00405   
00406   G4IntersectionSolid *magTubs =
00407     new G4IntersectionSolid(itsName+"_solid",
00408                             magTubsEnv,
00409                             markerSolidVolume,
00410                             RotYM90,
00411                             0); 
00412 
00413   if(OuterMaterialIsVacuum)
00414     {
00415       itsOuterLogicalVolume = 
00416         new G4LogicalVolume(magTubs,
00417                             theMaterials->GetMaterial("Vacuum"),
00418                             itsName+"_outer");
00419     }
00420   else
00421     {
00422       itsOuterLogicalVolume=
00423         new G4LogicalVolume(magTubs,
00424                             material,
00425                             itsName+"_outer");
00426     }
00427 
00428   itsPhysiComp =
00429     new G4PVPlacement(
00430                       RotY90,                 // rotation
00431                       0,                      // at (0,0,0)
00432                       itsOuterLogicalVolume,  // its logical volume
00433                       itsName+"_solid",       // its name
00434                       itsMarkerLogicalVolume, // its mother  volume
00435                       false,                  // no boolean operation
00436                       0,                     // copy number
00437                       true);// true --> check for overlaps with existing volumes
00438   itsOuterUserLimits =
00439     new G4UserLimits("multipole cut",DBL_MAX,DBL_MAX,DBL_MAX,
00440                      BDSGlobals->GetThresholdCutCharged());
00441   itsOuterUserLimits->SetMaxAllowedStep(itsLength);
00442   itsOuterLogicalVolume->SetUserLimits(itsOuterUserLimits);
00443 }
00444 
00445 BDSSectorBend::~BDSSectorBend()
00446 {
00447   delete itsVisAttributes;
00448   delete itsMarkerLogicalVolume;
00449   delete itsOuterLogicalVolume;
00450   delete itsPhysiComp;
00451   delete itsMagField;
00452   delete itsEqRhs;
00453   delete itsStepper;
00454   if (markerSolidVolume) delete markerSolidVolume;
00455 }

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