00001 #include "BDSGlobalConstants.hh"
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
00049
00050 BuildSBMarkerLogicalVolume();
00051
00052
00053
00054
00055 BuildBPFieldAndStepper();
00056 BuildBPFieldMgr(itsStepper,itsMagField);
00057 BuildSBBeampipe();
00058
00059
00060
00061
00062 BuildSBOuterLogicalVolume();
00063 if(BDSGlobals->GetIncludeIronMagFields())
00064 {
00065 G4double polePos[4];
00066 G4double Bfield[3];
00067
00068
00069 polePos[0]=0.;
00070 polePos[1]=BDSGlobals->GetMagnetPoleRadius();
00071 polePos[2]=0.;
00072 polePos[3]=-999.;
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
00082 BFldIron/=2.;
00083
00084 BuildOuterFieldManager(2, BFldIron,pi/2);
00085 }
00086
00087
00088
00089
00090 SetMultipleSensitiveVolumes(itsBeampipeLogicalVolume);
00091 SetMultipleSensitiveVolumes(itsOuterLogicalVolume);
00092
00093
00094
00095
00096 itsVisAttributes=SetVisAttributes();
00097 itsVisAttributes->SetForceSolid(true);
00098 itsOuterLogicalVolume->SetVisAttributes(itsVisAttributes);
00099
00100
00101
00102
00103 (*LogVolCount)[itsName]=1;
00104 (*LogVol)[itsName]=itsMarkerLogicalVolume;
00105 }
00106 else
00107 {
00108 (*LogVolCount)[itsName]++;
00109 if(BDSGlobals->GetSynchRadOn()&& BDSGlobals->GetSynchRescale())
00110 {
00111
00112
00113
00114 itsName+=BDSGlobals->StringFromInt((*LogVolCount)[itsName]);
00115
00116
00117
00118
00119 BuildSBMarkerLogicalVolume();
00120
00121
00122
00123
00124 BuildBPFieldAndStepper();
00125 BuildBPFieldMgr(itsStepper,itsMagField);
00126 BuildSBBeampipe();
00127
00128
00129
00130
00131 BuildSBOuterLogicalVolume();
00132 if(BDSGlobals->GetIncludeIronMagFields())
00133 {
00134 G4double polePos[4];
00135 G4double Bfield[3];
00136
00137
00138 polePos[0]=0.;
00139 polePos[1]=BDSGlobals->GetMagnetPoleRadius();
00140 polePos[2]=0.;
00141 polePos[3]=-999.;
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
00151 BFldIron/=2.;
00152
00153 BuildOuterFieldManager(2, BFldIron,pi/2);
00154 }
00155
00156
00157
00158
00159
00160 SetSensitiveVolume(itsBeampipeLogicalVolume);
00161
00162
00163
00164
00165
00166 itsVisAttributes=SetVisAttributes();
00167 itsVisAttributes->SetForceSolid(true);
00168 itsOuterLogicalVolume->SetVisAttributes(itsVisAttributes);
00169
00170
00171
00172
00173 (*LogVol)[itsName]=itsMarkerLogicalVolume;
00174 }
00175 else
00176 {
00177
00178
00179
00180 itsMarkerLogicalVolume=(*LogVol)[itsName];
00181 }
00182 }
00183 }
00184
00185 void BDSSectorBend::SynchRescale(G4double factor)
00186 {
00187
00188 itsStepper->SetBGrad(itsBGrad*factor);
00189 itsStepper->SetBField(-itsBField*factor);
00190
00191
00192
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));
00199 return itsVisAttributes;
00200 }
00201
00202 void BDSSectorBend::BuildBPFieldAndStepper()
00203 {
00204
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);
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,
00231 xHalfLengthMinus,
00232 boxSize/2,
00233 boxSize/2,
00234 fabs(cos(itsAngle/2))*boxSize/2);
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
00250
00251 itsMarkerLogicalVolume->
00252 SetFieldManager(BDSGlobals->GetZeroFieldManager(),false);
00253 }
00254
00255
00256
00257 void BDSSectorBend::BuildSBBeampipe()
00258 {
00259
00260
00261
00262 G4Material *material = theMaterials->GetMaterial( BDSGlobals->GetPipeMaterialName());
00263
00264
00265
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
00284
00285 G4Tubs *pipeTubsEnv = new G4Tubs(itsName+"_pipe_outer_env",
00286 itsBpRadius-bpThickness,
00287 itsBpRadius,
00288 tubLen,
00289 0,
00290 twopi * rad );
00291
00292 G4Tubs *pipeInnerEnv = new G4Tubs(itsName+"_pipe_inner_env",
00293 0,
00294 itsBpRadius-bpThickness,
00295 tubLen,
00296 0,
00297 twopi * rad );
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,
00327 0,
00328 itsInnerBPLogicalVolume,
00329 itsName+"_InnerBmp",
00330 itsMarkerLogicalVolume,
00331 false,
00332 0,
00333 true);
00334 G4VPhysicalVolume* PhysiComp;
00335 PhysiComp =
00336 new G4PVPlacement(
00337 RotY90,
00338 0,
00339 itsBeampipeLogicalVolume,
00340 itsName+"_bmp",
00341 itsMarkerLogicalVolume,
00342 false,
00343 0,
00344 true);
00345
00346
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
00362
00363 itsBeampipeLogicalVolume->SetFieldManager(BDSGlobals->GetZeroFieldManager(),false);
00364 itsInnerBPLogicalVolume->SetFieldManager(itsBPFieldMgr,false);
00365
00366
00367
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,
00401 itsOuterR,
00402 tubLen,
00403 0,
00404 twopi * rad );
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,
00431 0,
00432 itsOuterLogicalVolume,
00433 itsName+"_solid",
00434 itsMarkerLogicalVolume,
00435 false,
00436 0,
00437 true);
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 }