/home/cern/BDSIM_new/src/mySectorBend.cc

00001 #include "BDSGlobalConstants.hh" // must be first in include list
00002 
00003 #include "mySectorBend.hh"
00004 #include "G4Box.hh"
00005 #include "G4Torus.hh"
00006 #include "G4IntersectionSolid.hh"
00007 #include "G4VisAttributes.hh"
00008 #include "G4LogicalVolume.hh"
00009 #include "G4VPhysicalVolume.hh"
00010 #include "G4UserLimits.hh"
00011 #include "G4TransportationManager.hh"
00012 #include "G4PropagatorInField.hh"
00013 #include "G4SubtractionSolid.hh"
00014 
00015 #include <map>
00016 
00017 const int DEBUG = 0;
00018 
00019 //============================================================
00020 
00021 typedef std::map<G4String,int> LogVolCountMap;
00022 extern LogVolCountMap* LogVolCount;
00023 
00024 typedef std::map<G4String,G4LogicalVolume*> LogVolMap;
00025 extern LogVolMap* LogVol;
00026 
00027 extern BDSMaterials* theMaterials;
00028 extern G4RotationMatrix* RotY90;
00029 extern G4RotationMatrix* RotX90;
00030 
00031 //============================================================
00032 
00033 mySectorBend::mySectorBend(G4String aName,G4double aLength, 
00034                            G4double bpRad,G4double FeRad,
00035                            G4double bField, G4double angle, G4double outR,
00036                            G4double tilt,  G4double bGrad, 
00037                            G4String aMaterial, G4int nSegments):
00038   BDSMultipole(aName,aLength,bpRad,FeRad,SetVisAttributes(),aMaterial,0,0,angle)
00039 {
00040 
00041   if (outR==0) 
00042     SetOuterRadius(BDSGlobals->GetComponentBoxSize()/2);
00043   else
00044     SetOuterRadius(outR);
00045   itsTilt = tilt;
00046   itsBField = bField;
00047   itsBGrad = bGrad;
00048 
00049   itsType="sbend";
00050 
00051   if (!(*LogVolCount)[itsName] )
00052     {
00053       BuildSBMarkerLogicalVolume();
00054 
00055       BuildSBBeampipe();
00056 
00057       BuildBPFieldAndStepper();
00058 
00059       BuildBPFieldMgr(itsStepper,itsMagField);
00060 
00061       BuildSBOuterLogicalVolume();
00062 
00063       SetMultipleSensitiveVolumes(itsBeampipeLogicalVolume);
00064       SetMultipleSensitiveVolumes(itsOuterLogicalVolume);
00065 
00066       if(BDSGlobals->GetIncludeIronMagFields())
00067         {
00068           G4double polePos[4];
00069           G4double Bfield[3];
00070 
00071           polePos[0]=0.;
00072           polePos[1]=BDSGlobals->GetMagnetPoleRadius();
00073           polePos[2]=0.;
00074           polePos[0]=-999.;//flag to use polePos rather than local track
00075           //coordinate in GetFieldValue     
00076           
00077           itsMagField->GetFieldValue(polePos,Bfield);
00078           G4double BFldIron=
00079           sqrt(Bfield[0]*Bfield[0]+Bfield[1]*Bfield[1])*
00080           BDSGlobals->GetMagnetPoleSize()/
00081           (BDSGlobals->GetComponentBoxSize()/2-
00082           BDSGlobals->GetMagnetPoleRadius());
00083 
00084           // Magnetic flux from a pole is divided in two directions
00085           BFldIron/=2.;
00086           
00087           //BuildOuterFieldManager(2, BFldIron,0);
00088         }
00089 
00090       
00091       // vis attr
00092       G4VisAttributes* VisAtt = 
00093         new G4VisAttributes(G4Colour(0., 0., 0));
00094       VisAtt->SetForceSolid(true);
00095       itsInnerBPLogicalVolume->SetVisAttributes(VisAtt);
00096       
00097       G4VisAttributes* VisAtt1 = 
00098         new G4VisAttributes(G4Colour(0.1, 0.1, 0.1));
00099       VisAtt1->SetForceSolid(true);
00100       itsBeampipeLogicalVolume->SetVisAttributes(VisAtt1);
00101       
00102       G4VisAttributes* VisAtt2 = 
00103         new G4VisAttributes(G4Colour(0., 0., 1.));
00104       VisAtt2->SetForceSolid(true);
00105       itsOuterLogicalVolume->SetVisAttributes(VisAtt2);
00106       
00107 
00108       (*LogVolCount)[itsName]=1;
00109       (*LogVol)[itsName]=itsMarkerLogicalVolume;
00110     }
00111   else
00112     {
00113       (*LogVolCount)[itsName]++;
00114       if(BDSGlobals->GetSynchRadOn()&& BDSGlobals->GetSynchRescale())
00115         {
00116           // with synchrotron radiation, the rescaled magnetic field
00117           // means elements with the same name must have different
00118           //logical volumes, becuase they have different fields
00119           itsName+=BDSGlobals->StringFromInt((*LogVolCount)[itsName]);
00120 
00121           BuildSBMarkerLogicalVolume();
00122 
00123           BuildSBBeampipe();
00124         
00125           BuildBPFieldAndStepper();
00126 
00127           BuildBPFieldMgr(itsStepper,itsMagField);
00128 
00129           BuildSBOuterLogicalVolume();
00130 
00131           SetMultipleSensitiveVolumes(itsBeampipeLogicalVolume);
00132           SetMultipleSensitiveVolumes(itsOuterLogicalVolume);
00133 
00134           // vis attr
00135           G4VisAttributes* VisAtt = 
00136             new G4VisAttributes(G4Colour(0., 0., 0));
00137           VisAtt->SetForceSolid(true);
00138           itsInnerBPLogicalVolume->SetVisAttributes(VisAtt);
00139           
00140           G4VisAttributes* VisAtt1 = 
00141             new G4VisAttributes(G4Colour(0.1, 0.1, 0.1));
00142           VisAtt1->SetForceSolid(true);
00143           itsBeampipeLogicalVolume->SetVisAttributes(VisAtt1);
00144           
00145           G4VisAttributes* VisAtt2 = 
00146             new G4VisAttributes(G4Colour(0., 0., 1.));
00147           VisAtt2->SetForceSolid(true);
00148           itsOuterLogicalVolume->SetVisAttributes(VisAtt2);
00149           
00150           
00151           (*LogVol)[itsName]=itsMarkerLogicalVolume;
00152         }
00153       else
00154         {
00155           itsMarkerLogicalVolume=(*LogVol)[itsName];
00156         }      
00157     }
00158 }
00159 
00160 void mySectorBend::SynchRescale(G4double factor)
00161 {
00162   itsStepper->SetBGrad(itsBGrad*factor);
00163   itsStepper->SetBField(-itsBField*factor);
00164   // note that there are no methods to set the BDSSBendMagField as this
00165   // class does not do anything with the BFields.
00166   if(DEBUG) G4cout << "Sbend " << itsName << " has been scaled" << G4endl;
00167 }
00168 
00169 G4VisAttributes* mySectorBend::SetVisAttributes()
00170 {
00171   itsVisAttributes=new G4VisAttributes(G4Colour(0,1,1));
00172   return itsVisAttributes;
00173 }
00174 
00175 
00176 void mySectorBend::BuildBPFieldAndStepper()
00177 {
00178   // set up the magnetic field and stepper
00179   G4ThreeVector Bfield(0.,-itsBField,0.);
00180   itsMagField=new BDSSbendMagField(Bfield,itsLength,itsAngle);
00181   
00182   itsEqRhs=new G4Mag_UsualEqRhs(itsMagField);  
00183   
00184   itsStepper = new myQuadStepper(itsEqRhs); // note the - sign...
00185   itsStepper->SetBField(-itsBField);
00186   itsStepper->SetBGrad(itsBGrad);
00187 
00188   BuildBPFieldMgr(itsStepper,itsMagField);
00189 
00190   itsBeampipeLogicalVolume->SetFieldManager(BDSGlobals->GetZeroFieldManager(),false);
00191   itsInnerBPLogicalVolume->SetFieldManager(itsBPFieldMgr,false);
00192 
00193 }
00194 
00195 
00196 void mySectorBend::BuildSBMarkerLogicalVolume()
00197 {
00198   // radius of curvature
00199   G4double rho = itsLength/fabs(itsAngle);
00200 
00201   itsMarkerLogicalVolume=    
00202     new G4LogicalVolume(new G4Torus(itsName+"_marker",
00203                                     0,               // inner R
00204                                     itsOuterR,       // outer R
00205                                     rho,             // swept R
00206                                     0,               // starting phi
00207                                     fabs(itsAngle)), // delta phi
00208                         theMaterials->GetMaterial("Vacuum"),
00209                         itsName+"_marker");
00210 
00211   itsMarkerUserLimits = new G4UserLimits(DBL_MAX,DBL_MAX,DBL_MAX);
00212   itsMarkerUserLimits->SetMaxAllowedStep(itsLength);
00213   itsMarkerLogicalVolume->SetUserLimits(itsMarkerUserLimits);
00214 }
00215 
00216 
00217 // construct a beampipe for sector bend
00218 void mySectorBend::BuildSBBeampipe()
00219 {
00220   //
00221   // 1) construct the solids
00222   //
00223 
00224   // radius of curvature
00225   G4double rho = itsLength/fabs(itsAngle);
00226 
00227   // *** toroidal beampipes - problems with G4Torus::DistanceToTorus
00228   // *** when calling G4PolynomialSolver.Solve()
00229   G4double bpThickness = BDSGlobals->GetBeampipeThickness();
00230   G4Torus *pipeTube = new G4Torus(itsName+"_pipe_outer",
00231                                   itsBpRadius-bpThickness, // innerR
00232                                   itsBpRadius,             // outer R
00233                                   rho,                     // swept R
00234                                   0,                       // starting phi
00235                                   fabs(itsAngle) );        // delta phi
00236   
00237   
00238   G4Torus *pipeInner = new G4Torus(itsName+"_pipe_inner",
00239                                    0,                       // inner R
00240                                    itsBpRadius-bpThickness, // outer R
00241                                    rho,                     // swept R
00242                                    0,                       // starting phi
00243                                    fabs(itsAngle) );        // delta phi
00244 
00245 
00246   //
00247   // 2) construct the logical volumes (solids+materials)
00248   //
00249 
00250   // use default beampipe material
00251   G4Material *material =  theMaterials->GetMaterial( BDSGlobals->GetPipeMaterialName());
00252   
00253   itsBeampipeLogicalVolume=     
00254     new G4LogicalVolume(pipeTube,
00255                         material,
00256                         itsName+"_bmp_logical");
00257   
00258   itsInnerBPLogicalVolume=      
00259     new G4LogicalVolume(pipeInner,
00260                         theMaterials->GetMaterial("Vacuum"),
00261                         itsName+"_bmp_Inner_log");
00262 
00263 
00264   //
00265   // 3) position the logical volumes inside the mother volume (the marker)
00266   //
00267 
00268   G4VPhysicalVolume* PhysiInner;
00269   PhysiInner = 
00270     new G4PVPlacement(
00271                       0,                       // no rotation
00272                       0,                       // no translation
00273                       itsInnerBPLogicalVolume, // its logical volume
00274                       itsName+"_InnerBmp",     // its name
00275                       itsMarkerLogicalVolume,  // its mother volume
00276                       false,                   // no boolean operation
00277                       0);                      // copy number
00278 
00279   G4VPhysicalVolume* PhysiComp;
00280   PhysiComp = 
00281     new G4PVPlacement(
00282                       0,                       // no rotation
00283                       0,                       // no translation
00284                       itsBeampipeLogicalVolume,// its logical volume
00285                       itsName+"_bmp",          // its name
00286                       itsMarkerLogicalVolume,  // its mother  volume
00287                       false,                   // no boolean operation
00288                       0);                            // copy number
00289   
00290   itsBeampipeUserLimits =
00291     new G4UserLimits("beampipe cuts",DBL_MAX,DBL_MAX,DBL_MAX,
00292                      BDSGlobals->GetThresholdCutCharged());
00293   
00294   itsInnerBeampipeUserLimits =
00295     new G4UserLimits("inner beampipe cuts",DBL_MAX,DBL_MAX,DBL_MAX,
00296                      BDSGlobals->GetThresholdCutCharged());
00297   /*  
00298   itsOuterUserLimits =
00299     new G4UserLimits("sbend cut",itsLength,DBL_MAX,DBL_MAX,
00300                      BDSGlobals->GetThresholdCutCharged());
00301   
00302   itsOuterLogicalVolume->SetUserLimits(itsOuterUserLimits);
00303   */
00304   itsBeampipeUserLimits->SetMaxAllowedStep(itsLength);
00305   itsBeampipeLogicalVolume->SetUserLimits(itsBeampipeUserLimits);
00306   
00307   itsInnerBeampipeUserLimits->SetMaxAllowedStep(itsLength);
00308   itsInnerBPLogicalVolume->SetUserLimits(itsInnerBeampipeUserLimits);
00309 
00310   // zero field in the marker volume
00311   itsMarkerLogicalVolume->
00312     SetFieldManager(BDSGlobals->GetZeroFieldManager(),false);
00313 
00314 }
00315 
00316 void mySectorBend::BuildSBOuterLogicalVolume(G4bool OuterMaterialIsVacuum)
00317 {
00318   // radius of curvature
00319   G4double rho = itsLength/fabs(itsAngle);
00320 
00321   // compute sagitta (???)
00322   // G4double sagitta=0.;
00323   // if(itsNSegments>0)
00324   //   {
00325   //     sagitta=(itsLength/itsAngle*(1.-cos(itsAngle/2.)))/itsNSegments;
00326   //   }
00327 
00328   G4Material* material;
00329   if(itsMaterial != "") material = theMaterials->GetMaterial(itsMaterial);
00330   else material = theMaterials->GetMaterial("Iron");
00331 
00332   if(OuterMaterialIsVacuum)
00333     {
00334     itsOuterLogicalVolume=
00335       new G4LogicalVolume(new G4Torus(itsName+"_solid",
00336                                       itsInnerIronRadius, // inner R
00337                                       itsOuterR,          // outer R
00338                                       rho,                // swept R
00339                                       0,                  // starting phi
00340                                       fabs(itsAngle) ),   // delta phi
00341                           theMaterials->GetMaterial("Vacuum"),
00342                           itsName+"_outer");
00343     }
00344 
00345   if(!OuterMaterialIsVacuum)
00346     {
00347     itsOuterLogicalVolume=
00348       new G4LogicalVolume(new G4Torus(itsName+"_solid",
00349                                       itsInnerIronRadius, // inner R
00350                                       itsOuterR,          // outer R
00351                                       rho,                // swept R
00352                                       0,                  // starting phi
00353                                       fabs(itsAngle) ),   // delta phi
00354                           material,
00355                           itsName+"_outer");
00356     }
00357 
00358   G4VPhysicalVolume* itsPhysiComp;
00359   itsPhysiComp =
00360     new G4PVPlacement(
00361                       0,                        // no rotation
00362                       0,                        // no translation
00363                       itsOuterLogicalVolume,    // its logical volume
00364                       itsName+"_solid",         // its name
00365                       itsMarkerLogicalVolume,   // its mother  volume
00366                       false,                    // no boolean operation
00367                       0);                       // copy number
00368 
00369   itsOuterUserLimits =
00370     new G4UserLimits("multipole cut",itsLength,DBL_MAX,DBL_MAX,
00371                      BDSGlobals->GetThresholdCutCharged());
00372   //  itsOuterUserLimits->SetMaxAllowedStep(aLength);
00373   itsOuterLogicalVolume->SetUserLimits(itsOuterUserLimits);
00374 
00375 }
00376 
00377 mySectorBend::~mySectorBend()
00378 {
00379   delete itsVisAttributes;
00380   delete itsMarkerLogicalVolume;
00381   delete itsOuterLogicalVolume;
00382   delete itsPhysiComp;
00383   delete itsMagField;
00384   delete itsEqRhs;
00385   delete itsStepper;
00386 }

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