00001 #include "BDSGlobalConstants.hh"
00002
00003 #include "BDSSectorBend.hh"
00004 #include "G4Tubs.hh"
00005 #include "G4Trd.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
00013 #include <map>
00014
00015
00016
00017 typedef std::map<G4String,int> LogVolCountMap;
00018 extern LogVolCountMap* LogVolCount;
00019
00020 typedef std::map<G4String,G4LogicalVolume*> LogVolMap;
00021 extern LogVolMap* LogVol;
00022
00023
00024 extern G4RotationMatrix* RotY90;
00025 extern G4RotationMatrix* RotYM90;
00026
00027
00028
00029 BDSSectorBend::BDSSectorBend(G4String aName, G4double aLength,
00030 G4double bpRad, G4double FeRad,
00031 G4double bField, G4double angle, G4double outR,
00032 std::list<G4double> blmLocZ, std::list<G4double> blmLocTheta,
00033 G4double tilt, G4double bGrad,
00034 G4String aTunnelMaterial, G4String aMaterial, G4double aXAper, G4double aYAper):
00035 BDSMultipole(aName, aLength, bpRad, FeRad, SetVisAttributes(), blmLocZ, blmLocTheta, aTunnelMaterial, aMaterial,
00036 aXAper, aYAper, angle),
00037 itsStepper(NULL),itsMagField(NULL),itsEqRhs(NULL)
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 G4VisAttributes* VisAtt1 = new G4VisAttributes(G4Colour(0.4, 0.4, 0.4));
00052 VisAtt1->SetVisibility(true);
00053 VisAtt1->SetForceSolid(true);
00054 itsMarkerLogicalVolume->SetVisAttributes(VisAtt1);
00055
00056
00057
00058
00059
00060 if(BDSGlobalConstants::Instance()->GetBuildTunnel()){
00061 BuildTunnel();
00062 }
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 BuildBPFieldAndStepper();
00074 BuildBPFieldMgr(itsStepper,itsMagField);
00075 BuildSBBeampipe();
00076
00077
00078
00079
00080
00081
00082 BuildSBOuterLogicalVolume();
00083 if(BDSGlobalConstants::Instance()->GetIncludeIronMagFields())
00084 {
00085 G4double polePos[4];
00086 G4double Bfield[3];
00087
00088
00089 polePos[0]=0.;
00090 polePos[1]=BDSGlobalConstants::Instance()->GetMagnetPoleRadius();
00091 polePos[2]=0.;
00092 polePos[3]=-999.;
00093
00094 itsMagField->GetFieldValue(polePos,Bfield);
00095 G4double BFldIron=
00096 sqrt(Bfield[0]*Bfield[0]+Bfield[1]*Bfield[1])*
00097 BDSGlobalConstants::Instance()->GetMagnetPoleSize()/
00098 (BDSGlobalConstants::Instance()->GetComponentBoxSize()/2-
00099 BDSGlobalConstants::Instance()->GetMagnetPoleRadius());
00100
00101
00102 BFldIron/=2.;
00103
00104 BuildOuterFieldManager(2, BFldIron,pi/2);
00105 }
00106
00107
00108
00109
00110
00111
00112 if(BDSGlobalConstants::Instance()->GetSensitiveBeamPipe()){
00113 SetMultipleSensitiveVolumes(itsBeampipeLogicalVolume);
00114 }
00115 if(BDSGlobalConstants::Instance()->GetSensitiveComponents()){
00116 SetMultipleSensitiveVolumes(itsOuterLogicalVolume);
00117 }
00118
00119
00120
00121
00122
00123 itsVisAttributes=SetVisAttributes();
00124
00125 itsOuterLogicalVolume->SetVisAttributes(itsVisAttributes);
00126
00127
00128
00129
00130 (*LogVolCount)[itsName]=1;
00131 (*LogVol)[itsName]=itsMarkerLogicalVolume;
00132 }
00133 else
00134 {
00135 (*LogVolCount)[itsName]++;
00136 if(BDSGlobalConstants::Instance()->GetSynchRadOn()&& BDSGlobalConstants::Instance()->GetSynchRescale())
00137 {
00138
00139
00140
00141 itsName+=BDSGlobalConstants::Instance()->StringFromInt((*LogVolCount)[itsName]);
00142
00143
00144
00145
00146 BuildSBMarkerLogicalVolume();
00147
00148
00149
00150
00151 BuildBPFieldAndStepper();
00152 BuildBPFieldMgr(itsStepper,itsMagField);
00153 BuildSBBeampipe();
00154
00155
00156
00157
00158 BuildSBOuterLogicalVolume();
00159 if(BDSGlobalConstants::Instance()->GetIncludeIronMagFields())
00160 {
00161 G4double polePos[4];
00162 G4double Bfield[3];
00163
00164
00165 polePos[0]=0.;
00166 polePos[1]=BDSGlobalConstants::Instance()->GetMagnetPoleRadius();
00167 polePos[2]=0.;
00168 polePos[3]=-999.;
00169
00170 itsMagField->GetFieldValue(polePos,Bfield);
00171 G4double BFldIron=
00172 sqrt(Bfield[0]*Bfield[0]+Bfield[1]*Bfield[1])*
00173 BDSGlobalConstants::Instance()->GetMagnetPoleSize()/
00174 (BDSGlobalConstants::Instance()->GetComponentBoxSize()/2-
00175 BDSGlobalConstants::Instance()->GetMagnetPoleRadius());
00176
00177
00178 BFldIron/=2.;
00179
00180 BuildOuterFieldManager(2, BFldIron,pi/2);
00181 }
00182
00183
00184
00185
00186
00187 SetSensitiveVolume(itsBeampipeLogicalVolume);
00188
00189
00190
00191
00192
00193 itsVisAttributes=SetVisAttributes();
00194 itsVisAttributes->SetForceSolid(true);
00195 itsOuterLogicalVolume->SetVisAttributes(itsVisAttributes);
00196
00197
00198
00199
00200 (*LogVol)[itsName]=itsMarkerLogicalVolume;
00201 }
00202 else
00203 {
00204
00205
00206
00207 itsMarkerLogicalVolume=(*LogVol)[itsName];
00208 itsVisAttributes=SetVisAttributes();
00209 itsVisAttributes->SetForceSolid(true);
00210 }
00211 }
00212
00213 BuildBLMs();
00214 }
00215
00216 void BDSSectorBend::SynchRescale(G4double factor)
00217 {
00218
00219 itsStepper->SetBGrad(itsBGrad*factor);
00220 itsStepper->SetBField(-itsBField*factor);
00221
00222
00223
00224 #ifdef DEBUG
00225 G4cout << "Sbend " << itsName << " has been scaled" << G4endl;
00226 #endif
00227 }
00228
00229 G4VisAttributes* BDSSectorBend::SetVisAttributes()
00230 {
00231 itsVisAttributes = new G4VisAttributes(G4Colour(0,0,1));
00232 itsVisAttributes->SetForceSolid(true);
00233 itsVisAttributes->SetVisibility(true);
00234 return itsVisAttributes;
00235 }
00236
00237 void BDSSectorBend::BuildBPFieldAndStepper()
00238 {
00239
00240 G4ThreeVector Bfield(0.,-itsBField,0.);
00241 itsMagField=new BDSSbendMagField(Bfield,itsLength,itsAngle);
00242
00243 itsEqRhs=new G4Mag_UsualEqRhs(itsMagField);
00244
00245 itsStepper = new myQuadStepper(itsEqRhs);
00246 itsStepper->SetBField(-itsBField);
00247 itsStepper->SetBGrad(itsBGrad);
00248 }
00249
00250 void BDSSectorBend::BuildSBMarkerLogicalVolume()
00251 {
00252 G4double xLength, yLength;
00253 xLength = yLength = std::max(itsOuterR,BDSGlobalConstants::Instance()->GetComponentBoxSize()/2);
00254 xLength = std::max(xLength, this->GetTunnelRadius()+2*std::abs(this->GetTunnelOffsetX()) + BDSGlobalConstants::Instance()->GetTunnelThickness()+BDSGlobalConstants::Instance()->GetTunnelSoilThickness() + 4*BDSGlobalConstants::Instance()->GetLengthSafety() );
00255 yLength = std::max(yLength, this->GetTunnelRadius()+2*std::abs(BDSGlobalConstants::Instance()->GetTunnelOffsetY()) + BDSGlobalConstants::Instance()->GetTunnelThickness()+BDSGlobalConstants::Instance()->GetTunnelSoilThickness()+4*BDSGlobalConstants::Instance()->GetLengthSafety() );
00256
00257 G4double transverseSize=2*std::max(xLength, yLength);
00258
00259 #ifdef DEBUG
00260 G4cout<<"marker volume : x/y="<<transverseSize/m<<
00261 " m, l= "<< (itsLength)/2/m <<" m"<<G4endl;
00262 #endif
00263
00264 G4double xHalfLengthPlus, xHalfLengthMinus;
00265 if(fabs(itsAngle) > 1e-20){
00266 xHalfLengthMinus = (itsLength/itsAngle)*sin(itsAngle/2)
00267 - fabs(cos(itsAngle/2))*transverseSize*tan(itsAngle/2)/2;
00268
00269 xHalfLengthPlus = (itsLength/itsAngle)*sin(itsAngle/2)
00270 + fabs(cos(itsAngle/2))*transverseSize*tan(itsAngle/2)/2;
00271 } else {
00272 xHalfLengthPlus=(itsLength)/2.0;
00273 xHalfLengthMinus=(itsLength)/2.0;
00274 }
00275
00276 if((xHalfLengthPlus<0) || (xHalfLengthMinus<0)){
00277 G4cerr << "Bend radius in " << itsName << " too small for this tunnel/component geometry. Exiting." << G4endl;
00278 exit(1);
00279 }
00280
00281 itsMarkerSolidVolume = new G4Trd(itsName+"_marker",
00282 xHalfLengthPlus,
00283 xHalfLengthMinus,
00284 transverseSize/2,
00285 transverseSize/2,
00286 fabs(cos(itsAngle/2))*transverseSize/2);
00287
00288 G4String LocalLogicalName=itsName;
00289
00290 itsMarkerLogicalVolume=
00291 new G4LogicalVolume(itsMarkerSolidVolume,
00292 BDSMaterials::Instance()->GetMaterial(BDSGlobalConstants::Instance()->GetVacuumMaterial()),
00293 LocalLogicalName+"_marker");
00294
00295 itsMarkerUserLimits = new G4UserLimits(DBL_MAX,DBL_MAX,DBL_MAX, BDSGlobalConstants::Instance()->GetThresholdCutCharged());
00296 G4double maxStepFactor=0.5;
00297 itsMarkerUserLimits->SetMaxAllowedStep(itsLength*maxStepFactor);
00298 itsMarkerLogicalVolume->SetUserLimits(itsMarkerUserLimits);
00299
00300
00301
00302
00303
00304 itsMarkerLogicalVolume->
00305 SetFieldManager(BDSGlobalConstants::Instance()->GetZeroFieldManager(),false);
00306 }
00307
00308
00309
00310 void BDSSectorBend::BuildSBBeampipe()
00311 {
00312
00313
00314
00315 G4Material *material = BDSMaterials::Instance()->GetMaterial( BDSGlobalConstants::Instance()->GetPipeMaterialName());
00316
00317
00318
00319
00320
00321 G4double boxSize = BDSGlobalConstants::Instance()->GetComponentBoxSize();
00322
00323 G4double xHalfLengthPlus, xHalfLengthMinus, tubLen;
00324 if(itsAngle != 0){
00325 xHalfLengthMinus =
00326 (itsLength/itsAngle)*sin(itsAngle/2)
00327 - fabs(cos(itsAngle/2)) * boxSize * tan(itsAngle/2)/2;
00328
00329 xHalfLengthPlus =
00330 (itsLength/itsAngle)*sin(itsAngle/2)
00331 + fabs(cos(itsAngle/2)) * boxSize * tan(itsAngle/2)/2;
00332 tubLen = std::max(xHalfLengthPlus,xHalfLengthMinus);
00333 } else {
00334 tubLen=(itsLength)/2.0;
00335 }
00336
00337
00338
00339
00340
00341
00342 G4VSolid *pipeTubsEnv = new G4SubtractionSolid("_pipe_outer_env",
00343 new G4EllipticalTube(itsName+"_pipe_outer_tmp_1",
00344 this->GetAperX()+BDSGlobalConstants::Instance()->GetBeampipeThickness(),
00345 this->GetAperY()+BDSGlobalConstants::Instance()->GetBeampipeThickness(),
00346 tubLen),
00347 new G4EllipticalTube(itsName+"_pipe_outer_tmp_2",
00348 this->GetAperX()+BDSGlobalConstants::Instance()->GetLengthSafety()/2.0,
00349 this->GetAperY()+BDSGlobalConstants::Instance()->GetLengthSafety()/2.0,
00350 tubLen*2)
00351 );
00352
00353
00354
00355
00356 G4VSolid *pipeInnerEnv = new G4EllipticalTube(itsName+"_pipe_outer_tmp_2",
00357 this->GetAperX(),
00358 this->GetAperY(),
00359 tubLen);
00360
00361 G4IntersectionSolid *pipeTubs =
00362 new G4IntersectionSolid(itsName+"_pipe_outer",
00363 pipeTubsEnv,
00364 itsMarkerSolidVolume,
00365 RotYM90,
00366 (G4ThreeVector)0);
00367
00368 G4IntersectionSolid *pipeInner =
00369 new G4IntersectionSolid(itsName+"_pipe_inner",
00370 pipeInnerEnv,
00371 itsMarkerSolidVolume,
00372 RotYM90,
00373 (G4ThreeVector)0);
00374
00375 itsBeampipeLogicalVolume=
00376 new G4LogicalVolume(pipeTubs,
00377 material,
00378 itsName+"_bmp_logical");
00379
00380 itsInnerBPLogicalVolume=
00381 new G4LogicalVolume(pipeInner,
00382 BDSMaterials::Instance()->GetMaterial(BDSGlobalConstants::Instance()->GetVacuumMaterial()),
00383 itsName+"_bmp_Inner_log");
00384
00385 G4VPhysicalVolume* PhysiInner;
00386 PhysiInner =
00387 new G4PVPlacement(
00388 RotY90,
00389 (G4ThreeVector)0,
00390 itsInnerBPLogicalVolume,
00391 itsName+"_InnerBmp",
00392 itsMarkerLogicalVolume,
00393 false,
00394 0, BDSGlobalConstants::Instance()->GetCheckOverlaps());
00395
00396 SetMultiplePhysicalVolumes(PhysiInner);
00397
00398 G4VPhysicalVolume* PhysiComp;
00399 PhysiComp =
00400 new G4PVPlacement(
00401 RotY90,
00402 (G4ThreeVector)0,
00403 itsBeampipeLogicalVolume,
00404 itsName+"_bmp",
00405 itsMarkerLogicalVolume,
00406 false,
00407 0, BDSGlobalConstants::Instance()->GetCheckOverlaps());
00408
00409 SetMultiplePhysicalVolumes(PhysiComp);
00410
00411
00412
00413
00414 #ifndef NOUSERLIMITS
00415 itsBeampipeUserLimits =
00416 new G4UserLimits("beampipe cuts",DBL_MAX,DBL_MAX,DBL_MAX,
00417 BDSGlobalConstants::Instance()->GetThresholdCutCharged());
00418 G4double maxStepFactor=0.5;
00419 itsBeampipeUserLimits->SetMaxAllowedStep(itsLength*maxStepFactor);
00420 itsBeampipeUserLimits->SetUserMaxTime(BDSGlobalConstants::Instance()->GetMaxTime());
00421 itsBeampipeLogicalVolume->SetUserLimits(itsBeampipeUserLimits);
00422
00423 G4double maxStepFactorIn=0.5;
00424 itsInnerBeampipeUserLimits =
00425 new G4UserLimits("inner beampipe cuts",DBL_MAX,DBL_MAX,DBL_MAX,
00426 BDSGlobalConstants::Instance()->GetThresholdCutCharged());
00427 itsInnerBeampipeUserLimits->SetMaxAllowedStep(itsLength*maxStepFactorIn);
00428 itsInnerBeampipeUserLimits->SetUserMaxTime(BDSGlobalConstants::Instance()->GetMaxTime());
00429 itsInnerBPLogicalVolume->SetUserLimits(itsInnerBeampipeUserLimits);
00430 #endif
00431
00432
00433
00434
00435 itsBeampipeLogicalVolume->SetFieldManager(BDSGlobalConstants::Instance()->GetZeroFieldManager(),false);
00436 itsInnerBPLogicalVolume->SetFieldManager(itsBPFieldMgr,false);
00437
00438
00439
00440
00441 G4VisAttributes* VisAtt = new G4VisAttributes(G4Colour(0., 0., 0));
00442 VisAtt->SetForceSolid(true);
00443 itsInnerBPLogicalVolume->SetVisAttributes(VisAtt);
00444
00445 G4VisAttributes* VisAtt1 = new G4VisAttributes(G4Colour(0.4, 0.4, 0.4));
00446 VisAtt1->SetVisibility(true);
00447 VisAtt1->SetForceSolid(true);
00448 itsBeampipeLogicalVolume->SetVisAttributes(VisAtt1);
00449 }
00450
00451
00452 G4double BDSSectorBend::GetArcLength()
00453 {
00454
00455
00456 if (itsAngle == 0.0)
00457 return itsLength;
00458 else
00459 return (itsLength * (0.5*itsAngle) / sin(0.5*itsAngle));
00460 }
00461
00462 void BDSSectorBend::BuildSBOuterLogicalVolume(G4bool OuterMaterialIsVacuum){
00463
00464 G4Material* material;
00465
00466 if(itsMaterial != "")
00467 material = BDSMaterials::Instance()->GetMaterial(itsMaterial);
00468 else
00469 material = BDSMaterials::Instance()->GetMaterial("Iron");
00470
00471 G4double xHalfLengthPlus, xHalfLengthMinus, tubLen;
00472 if(itsAngle != 0){
00473 xHalfLengthMinus = (itsLength/itsAngle)*sin(itsAngle/2)
00474 - fabs(cos(itsAngle/2)) * BDSGlobalConstants::Instance()->GetComponentBoxSize() * tan(itsAngle/2)/2
00475 - BDSGlobalConstants::Instance()->GetLengthSafety()/2;
00476
00477 xHalfLengthPlus = (itsLength/itsAngle)*sin(itsAngle/2)
00478 + fabs(cos(itsAngle/2)) * BDSGlobalConstants::Instance()->GetComponentBoxSize() * tan(itsAngle/2)/2
00479 - BDSGlobalConstants::Instance()->GetLengthSafety()/2;
00480
00481 tubLen = std::max(xHalfLengthPlus,xHalfLengthMinus);
00482 } else {
00483 tubLen = (itsLength-BDSGlobalConstants::Instance()->GetLengthSafety())/2.0;
00484 }
00485
00486
00487 G4VSolid *magTubsEnv = new G4SubtractionSolid(itsName+"_solid_env",
00488 new G4Tubs(itsName+"_solid_tmp_1",
00489 itsInnerIronRadius + BDSGlobalConstants::Instance()->GetLengthSafety()/2.0,
00490 itsOuterR,
00491 tubLen,
00492 0,
00493 twopi * rad ),
00494 new G4EllipticalTube(itsName+"_pipe_outer_tmp_2",
00495 this->GetAperX()+BDSGlobalConstants::Instance()->GetBeampipeThickness()+BDSGlobalConstants::Instance()->GetLengthSafety()/2.0,
00496 this->GetAperY()+BDSGlobalConstants::Instance()->GetBeampipeThickness()+BDSGlobalConstants::Instance()->GetLengthSafety()/2.0,
00497 tubLen*2)
00498 );
00499
00500 G4IntersectionSolid *magTubs =
00501 new G4IntersectionSolid(itsName+"_solid",
00502 magTubsEnv,
00503 itsMarkerSolidVolume,
00504 RotYM90,
00505 (G4ThreeVector)0);
00506
00507 if(OuterMaterialIsVacuum)
00508 {
00509 itsOuterLogicalVolume =
00510 new G4LogicalVolume(magTubs,
00511 BDSMaterials::Instance()->GetMaterial(BDSGlobalConstants::Instance()->GetVacuumMaterial()),
00512 itsName+"_outer");
00513 }
00514 else
00515 {
00516 itsOuterLogicalVolume=
00517 new G4LogicalVolume(magTubs,
00518 material,
00519 itsName+"_outer");
00520 }
00521
00522 itsPhysiComp =
00523 new G4PVPlacement(
00524 RotY90,
00525 (G4ThreeVector)0,
00526 itsOuterLogicalVolume,
00527 itsName+"_solid",
00528 itsMarkerLogicalVolume,
00529 false,
00530 0, BDSGlobalConstants::Instance()->GetCheckOverlaps());
00531
00532 SetMultiplePhysicalVolumes(itsPhysiComp);
00533 G4double maxStepFactor=0.5;
00534
00535 #ifndef NOUSERLIMITS
00536 itsOuterUserLimits =
00537 new G4UserLimits("multipole cut",DBL_MAX,DBL_MAX,DBL_MAX,
00538 BDSGlobalConstants::Instance()->GetThresholdCutCharged());
00539 itsOuterUserLimits->SetMaxAllowedStep(itsLength*maxStepFactor);
00540 itsOuterUserLimits->SetUserMaxTime(BDSGlobalConstants::Instance()->GetMaxTime());
00541 itsOuterLogicalVolume->SetUserLimits(itsOuterUserLimits);
00542 #endif
00543 }
00544
00545 BDSSectorBend::~BDSSectorBend()
00546 {
00547 delete itsVisAttributes;
00548 delete itsMagField;
00549 delete itsEqRhs;
00550 delete itsStepper;
00551 }