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

00001 #include "BDSGlobalConstants.hh"
00002 #include "BDSDebug.hh"
00003 
00004 #include "BDSRBend.hh"
00005 
00006 #include "BDSBeamPipe.hh"
00007 #include "BDSBeamPipeFactory.hh"
00008 #include "BDSBeamPipeInfo.hh"
00009 #include "BDSDipoleStepper.hh"
00010 #include "BDSMagnetOuterInfo.hh"
00011 #include "BDSMagnetType.hh"
00012 #include "BDSMaterials.hh"
00013 #include "BDSSbendMagField.hh"
00014 #include "BDSUtilities.hh"
00015 
00016 #include "G4FieldManager.hh"
00017 #include "G4IntersectionSolid.hh"
00018 #include "G4LogicalVolume.hh"
00019 #include "G4Mag_EqRhs.hh"
00020 #include "G4PVPlacement.hh"
00021 #include "G4Tubs.hh"
00022 #include "G4CutTubs.hh"
00023 #include "G4UserLimits.hh"
00024 #include "G4VisAttributes.hh"
00025 #include "G4VPhysicalVolume.hh"
00026 
00027 BDSRBend::BDSRBend(G4String           name,
00028                    G4double           length,
00029                    G4double           bField,
00030                    G4double           bGrad,
00031                    G4double           angleIn,
00032                    BDSBeamPipeInfo*   beamPipeInfo,
00033                    BDSMagnetOuterInfo magnetOuterInfo,
00034                    BDSTiltOffset      tiltOffset):
00035   BDSMagnet(BDSMagnetType::rectangularbend, name, length,
00036             beamPipeInfo, magnetOuterInfo, tiltOffset),
00037   itsBField(bField),
00038   itsBGrad(bGrad)
00039 {
00040   angle       = angleIn;
00041   outerRadius = magnetOuterInfo.outerDiameter*0.5; 
00042   CommonConstructor(length);
00043 }
00044 
00045 
00046 void BDSRBend::CommonConstructor(G4double aLength)
00047 {
00048   //full length along chord - just its length in case of rbend
00049   chordLength = aLength;
00050 
00051   orientation = BDS::CalculateOrientation(angle);
00052 
00053   // itsStraightSectionChord is the distance along the chord required to be used by a drift pipe so that
00054   // the outer logical volume (magnet cylinder - defined by outRadius) doesn't protrude
00055   // into the previous volume / outside the marker volume.  for zero angle, this is 0
00056 
00057   itsStraightSectionChord     = outerRadius / (tan(0.5*fabs(angle)) + tan((0.5*CLHEP::pi) - (0.5*fabs(angle))) );
00058   itsMagFieldLength           = chordLength - (2.0*itsStraightSectionChord);
00059   magnetXShift                = orientation*itsStraightSectionChord*tan(0.5*fabs(angle));
00060   G4ThreeVector magpos        = G4ThreeVector(magnetXShift, 0, 0);
00061   G4double      dz            = (itsMagFieldLength*0.5)+(itsStraightSectionChord*0.5);
00062   G4ThreeVector driftposstart = G4ThreeVector(0.5*magnetXShift, 0, -1*dz);
00063   G4ThreeVector driftposend   = G4ThreeVector(0.5*magnetXShift, 0, dz);
00064   itsStraightSectionLength    = itsStraightSectionChord / (cos(0.5*fabs(angle)));
00065 
00066   G4double in_z = cos(0.5*fabs(angle)); // calculate components of normal vectors (in the end mag(normal) = 1)
00067   G4double in_x = sin(0.5*fabs(angle));
00068   inputface  = G4ThreeVector(-orientation*in_x, 0.0, -1.0*in_z); //-1 as pointing down in z for normal
00069   outputface = G4ThreeVector(-orientation*in_x, 0.0, in_z);
00070   
00071 #ifdef BDSDEBUG
00072   G4cout << __METHOD_NAME__ << "Angle                   = " << angle                    << G4endl;
00073   G4cout << __METHOD_NAME__ << "Straight section chord  = " << itsStraightSectionChord  << G4endl;
00074   G4cout << __METHOD_NAME__ << "Magnetic field length   = " << itsMagFieldLength        << G4endl;
00075   G4cout << __METHOD_NAME__ << "Straight section length = " << itsStraightSectionLength << G4endl;
00076   G4cout << __METHOD_NAME__ << "Straight section chord  = " << itsStraightSectionChord  << G4endl;
00077   G4cout << __METHOD_NAME__ << "Magnet shift in X       = " << magnetXShift             << G4endl;
00078 #endif
00079 }
00080 
00081 void BDSRBend::Build()
00082 {
00083   BDSMagnet::Build();
00084   if(BDSGlobalConstants::Instance()->GetIncludeIronMagFields())
00085     {
00086       G4double polePos[4];
00087       G4double Bfield[3];
00088       
00089       //coordinate in GetFieldValue
00090       polePos[0]=0.;
00091       polePos[1]=BDSGlobalConstants::Instance()->GetMagnetPoleRadius();
00092       polePos[2]=0.;
00093       polePos[3]=-999.;//flag to use polePos rather than local track
00094       
00095       itsMagField->GetFieldValue(polePos,Bfield);
00096       G4double BFldIron=
00097         sqrt(Bfield[0]*Bfield[0]+Bfield[1]*Bfield[1])*
00098         BDSGlobalConstants::Instance()->GetMagnetPoleSize()/
00099         (BDSGlobalConstants::Instance()->GetComponentBoxSize()/2-
00100          BDSGlobalConstants::Instance()->GetMagnetPoleRadius());
00101       
00102       // Magnetic flux from a pole is divided in two directions
00103       BFldIron/=2.;
00104       
00105       BuildOuterFieldManager(2, BFldIron,CLHEP::pi/2);
00106     }
00107 }
00108 
00109 void BDSRBend::BuildBPFieldAndStepper()
00110 {
00111   // set up the magnetic field and stepper
00112   G4ThreeVector Bfield(0.,-itsBField,0.);
00113   G4double arclength = fabs(angle) * ((itsMagFieldLength*0.5) / sin(0.5*fabs(angle)));
00114 #ifdef BDSDEBUG
00115   G4cout << __METHOD_NAME__ << " calculated arclength in dipole field: " << arclength << G4endl;
00116 #endif
00117   itsMagField = new BDSSbendMagField(Bfield,arclength,angle);
00118   itsEqRhs    = new G4Mag_UsualEqRhs(itsMagField);  
00119   
00120   BDSDipoleStepper* dipoleStepper = new BDSDipoleStepper(itsEqRhs);
00121   dipoleStepper->SetBField(-itsBField); // note the - sign...
00122   dipoleStepper->SetBGrad(itsBGrad);
00123   itsStepper = dipoleStepper;
00124 }
00125 
00126 void BDSRBend::BuildOuterVolume()
00127 {
00128   //need to make a shorter outer volume for rbend geometry
00129   //let's cheat and use the base class method by fiddling the
00130   //component length then setting it back - reduces code duplication
00131   G4double originalLength = chordLength;
00132   chordLength = itsMagFieldLength;
00133   BDSMagnet::BuildOuterVolume();
00134   chordLength = originalLength;
00135 }
00136 
00137 // construct a beampipe for r bend
00138 void BDSRBend::BuildBeampipe()
00139 {
00140   BDSBeamPipe* bpFirstBit =
00141     BDSBeamPipeFactory::Instance()->CreateBeamPipeAngledOut(beamPipeInfo->beamPipeType,
00142                                                             name,
00143                                                             itsStraightSectionLength,
00144                                                             -angle*0.5,
00145                                                             beamPipeInfo->aper1,
00146                                                             beamPipeInfo->aper2,
00147                                                             beamPipeInfo->aper3,
00148                                                             beamPipeInfo->aper4,
00149                                                             beamPipeInfo->vacuumMaterial,
00150                                                             beamPipeInfo->beamPipeThickness,
00151                                                             beamPipeInfo->beamPipeMaterial);
00152   
00153   beampipe =
00154     BDSBeamPipeFactory::Instance()->CreateBeamPipe(beamPipeInfo->beamPipeType,
00155                                                    name,
00156                                                    itsMagFieldLength,
00157                                                    beamPipeInfo->aper1,
00158                                                    beamPipeInfo->aper2,
00159                                                    beamPipeInfo->aper3,
00160                                                    beamPipeInfo->aper4,
00161                                                    beamPipeInfo->vacuumMaterial,
00162                                                    beamPipeInfo->beamPipeThickness,
00163                                                    beamPipeInfo->beamPipeMaterial);
00164 
00165   BDSBeamPipe* bpLastBit =
00166     BDSBeamPipeFactory::Instance()->CreateBeamPipeAngledIn(beamPipeInfo->beamPipeType,
00167                                                            name,
00168                                                            itsStraightSectionLength,
00169                                                            angle*0.5,
00170                                                            beamPipeInfo->aper1,
00171                                                            beamPipeInfo->aper2,
00172                                                            beamPipeInfo->aper3,
00173                                                            beamPipeInfo->aper4,
00174                                                            beamPipeInfo->vacuumMaterial,
00175                                                            beamPipeInfo->beamPipeThickness,
00176                                                            beamPipeInfo->beamPipeMaterial);
00177 
00178   // place logical volumes inside marker (container) volume
00179   // calculate offsets and rotations
00180   G4double straightSectionCentralZ = (itsMagFieldLength*0.5) + (itsStraightSectionChord*0.5);
00181   G4RotationMatrix* straightStartRM = new G4RotationMatrix();
00182   straightStartRM->rotateY(angle*0.5);
00183   G4RotationMatrix* straightEndRM = new G4RotationMatrix();
00184   straightEndRM->rotateY(-angle*0.5);
00185   straightEndRM->rotateZ(CLHEP::pi);
00186   G4ThreeVector straightStartPos = G4ThreeVector(orientation*magnetXShift*0.5,0,-straightSectionCentralZ);
00187   G4ThreeVector straightEndPos   = G4ThreeVector(orientation*magnetXShift*0.5,0,straightSectionCentralZ);
00188   G4ThreeVector magnetPos        = G4ThreeVector(orientation*magnetXShift,0,0);
00189   
00190   new G4PVPlacement(straightStartRM,                         // rotation
00191                     straightStartPos,                        // position
00192                     bpFirstBit->GetContainerLogicalVolume(), // logical volume
00193                     name+"_bp_start_phys",                // name
00194                     containerLogicalVolume,                  // mother volume
00195                     false,                                   // no booleanm operation
00196                     0,                                       // copy number
00197                     BDSGlobalConstants::Instance()->GetCheckOverlaps() );
00198 
00199    new G4PVPlacement(0,                                      // rotation
00200                      magnetPos,                              // position
00201                      beampipe->GetContainerLogicalVolume(),  // logical volume
00202                      name+"_bp_phys",                     // name
00203                      containerLogicalVolume,                 // mother volume
00204                      false,                                  // no boolean operation
00205                      0,                                      // copy number
00206                      BDSGlobalConstants::Instance()->GetCheckOverlaps() );
00207 
00208    new G4PVPlacement(straightEndRM,                          // rotation
00209                      straightEndPos,                         // position
00210                      bpLastBit->GetContainerLogicalVolume(), // logical volume
00211                      name+"_bp_end_phys",                    // name
00212                      containerLogicalVolume,                 // mother volume
00213                      false,                                  // no boolean operation
00214                      0,                                      // copy number
00215                      BDSGlobalConstants::Instance()->GetCheckOverlaps() );
00216 
00217    // can't use BeamPipeCommonTasks() as it places the beampipe volume and that'll be wrong in this case
00218    // have to do everything manually here
00219    beampipe->GetVacuumLogicalVolume()->SetFieldManager(itsBPFieldMgr,false);
00220    containerLogicalVolume->
00221     SetFieldManager(BDSGlobalConstants::Instance()->GetZeroFieldManager(),false);
00222    
00223    RegisterLogicalVolumes(bpFirstBit->GetAllLogicalVolumes());
00224    RegisterLogicalVolumes(beampipe->GetAllLogicalVolumes());
00225    RegisterLogicalVolumes(bpLastBit->GetAllLogicalVolumes());
00226 
00227    // register components as sensitive if required
00228    if(BDSGlobalConstants::Instance()->GetSensitiveBeamPipe())
00229      {
00230        RegisterSensitiveVolumes(bpFirstBit->GetAllSensitiveVolumes());
00231        RegisterSensitiveVolumes(beampipe->GetAllSensitiveVolumes());
00232        RegisterSensitiveVolumes(bpLastBit->GetAllSensitiveVolumes());
00233      }
00234    
00235    SetExtentX(beampipe->GetExtentX()); //not exact but only central porition will use this
00236    SetExtentY(beampipe->GetExtentY());
00237    SetExtentZ(-chordLength*0.5,chordLength*0.5);
00238 }

Generated on 28 Jun 2015 for BDSIM by  doxygen 1.4.7