00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "BDSGlobalConstants.hh"
00012
00013 #include <cstdlib>
00014
00015 #include "BDSMultipole.hh"
00016 #include "G4Box.hh"
00017 #include "G4Tubs.hh"
00018 #include "G4VisAttributes.hh"
00019 #include "G4LogicalVolume.hh"
00020 #include "G4VPhysicalVolume.hh"
00021 #include "G4UserLimits.hh"
00022 #include "G4TransportationManager.hh"
00023
00024 #include "G4MagIntegratorStepper.hh"
00025
00026 #include "BDSMultipoleOuterMagField.hh"
00027 #include "G4MagneticField.hh"
00028
00029 #include <map>
00030 #include <string>
00031
00032
00033 const int DEBUG= 0;
00034
00035
00036
00037 typedef std::map<G4String,int> LogVolCountMap;
00038 extern LogVolCountMap* LogVolCount;
00039
00040 typedef std::map<G4String,G4LogicalVolume*> LogVolMap;
00041 extern LogVolMap* LogVol;
00042
00043 extern BDSMaterials* theMaterials;
00044 extern G4RotationMatrix* RotY90;
00045
00046
00047
00048 BDSMultipole::BDSMultipole( G4String aName,
00049 G4double aLength,
00050 G4double aBpRadius,
00051 G4double aInnerIronRadius,
00052 G4VisAttributes* aVisAtt,
00053 G4String aMaterial,
00054 G4double aXAper,
00055 G4double aYAper,
00056 G4double angle):
00057 BDSAcceleratorComponent(
00058 aName,
00059 aLength,
00060 aBpRadius,
00061 aXAper,
00062 aYAper,
00063 aVisAtt,
00064 aMaterial,
00065 angle),
00066 itsInnerIronRadius(aInnerIronRadius)
00067 {}
00068
00069
00070 void BDSMultipole::BuildBeampipe(G4double aLength,
00071 G4String materialName,
00072 G4int nSegments)
00073 {
00074
00075 itsNSegments=nSegments;
00076 G4double dSegments=double(nSegments);
00077
00078 G4Material *material;
00079
00080 if(materialName == "")
00081 {
00082 material = theMaterials->GetMaterial( BDSGlobals->GetPipeMaterialName() );
00083 }
00084 else
00085 {
00086 material = theMaterials->GetMaterial(materialName);
00087 }
00088
00089
00090
00091 if(DEBUG) G4cout << "Outer pipe :"
00092 << " r= " << itsBpRadius/m << " m"
00093 << " l= " << aLength/(2.*dSegments)/m << " m"
00094 << G4endl;
00095
00096 itsBPTube=new G4Tubs(itsName+"_bmp_solid",
00097 itsBpRadius-BDSGlobals->GetBeampipeThickness(),
00098 itsBpRadius,
00099 aLength/(2.*dSegments),
00100 0,twopi*radian);
00101
00102 if(DEBUG) G4cout << "Inner pipe :"
00103 << " r= " << (itsBpRadius-BDSGlobals->GetBeampipeThickness() )/m
00104 << " m"
00105 << " l= " << aLength/(2.*dSegments)/m << " m"
00106 << G4endl;
00107
00108 if(nSegments==1)
00109 {
00110 itsInnerBPTube=new G4Tubs(itsName+"_inner_bmp_solid",
00111 0.,
00112 itsBpRadius-BDSGlobals->GetBeampipeThickness(),
00113 aLength/2,
00114 0,twopi*radian);
00115 }
00116 else
00117 {
00118 itsInnerBPTube=new G4Tubs(itsName+"_inner_bmp_solid",
00119 0.,
00120 itsBpRadius-BDSGlobals->GetBeampipeThickness(),
00121 aLength/(2.*dSegments)-
00122 itsBpRadius*tan(itsAngle/(2.*dSegments)),
00123 0,twopi*radian);
00124 }
00125
00126 itsBeampipeLogicalVolume=
00127 new G4LogicalVolume(itsBPTube,
00128 material,
00129 itsName+"_bmp_log");
00130
00131 itsInnerBPLogicalVolume=
00132 new G4LogicalVolume(itsInnerBPTube,
00133 theMaterials->GetMaterial("Vacuum"),
00134 itsName+"_inner_bmp_log");
00135
00136 G4VPhysicalVolume* PhysiInner;
00137 PhysiInner = new G4PVPlacement(
00138 0,
00139 0,
00140 itsInnerBPLogicalVolume,
00141 itsName+"_inner_bmp_phys",
00142 itsMarkerLogicalVolume,
00143 false,
00144 0);
00145
00146 if(nSegments==1)
00147 {
00148 G4RotationMatrix* Rot=NULL;
00149 if(itsAngle!=0 && itsType!="rbend") Rot=RotY90;
00150
00151
00152
00153
00154 G4VPhysicalVolume* PhysiComp;
00155 PhysiComp = new G4PVPlacement(
00156 Rot,
00157 0,
00158 itsBeampipeLogicalVolume,
00159 itsName+"_bmp_phys",
00160 itsMarkerLogicalVolume,
00161 false,
00162 0);
00163 }
00164 else
00165 {
00166 itsSegRot=new G4RotationMatrix();
00167 G4double DeltaRot=fabs(itsAngle)/(double(nSegments));
00168
00169 G4double angle=- fabs(itsAngle/2)-DeltaRot/2.;
00170 itsSegRot->rotateY(acos(0.) + angle );
00171
00172 G4double X,Y,Z,R,Z0;
00173
00174 R=itsLength/fabs(itsAngle);
00175 Z0=R*(1.-cos(fabs(itsAngle/2)-DeltaRot/2.));
00176
00177
00178 for(G4int iSeg=0;iSeg<nSegments;iSeg++)
00179 {
00180 itsSegRot->rotateY(DeltaRot);
00181 angle+=DeltaRot;
00182
00183
00184 X=R*sin(angle);
00185 Y=0.;
00186 Z=R*(1.-cos(angle))-Z0;
00187
00188
00189
00190 itsSegPos.setX(X);
00191 itsSegPos.setY(Y);
00192 itsSegPos.setZ(Z);
00193
00194 G4VPhysicalVolume* PhysiComp;
00195 PhysiComp = new G4PVPlacement(
00196 itsSegRot,
00197 itsSegPos,
00198 itsBeampipeLogicalVolume,
00199 itsName+"_bmp_phys",
00200 itsMarkerLogicalVolume,
00201 false,
00202 0);
00203 }
00204 }
00205
00206
00207 itsBeampipeUserLimits =
00208 new G4UserLimits("beampipe cuts",DBL_MAX,DBL_MAX,DBL_MAX,
00209 BDSGlobals->GetThresholdCutCharged());
00210
00211 itsInnerBeampipeUserLimits =
00212 new G4UserLimits("inner beampipe cuts",DBL_MAX,DBL_MAX,DBL_MAX,
00213 BDSGlobals->GetThresholdCutCharged());
00214
00215 itsBeampipeUserLimits->SetMaxAllowedStep(aLength);
00216 itsBeampipeLogicalVolume->SetUserLimits(itsBeampipeUserLimits);
00217
00218 itsInnerBeampipeUserLimits->SetMaxAllowedStep(aLength);
00219 itsInnerBPLogicalVolume->SetUserLimits(itsInnerBeampipeUserLimits);
00220
00221 itsBeampipeLogicalVolume->SetFieldManager(BDSGlobals->GetZeroFieldManager(),false);
00222 itsInnerBPLogicalVolume->SetFieldManager(itsBPFieldMgr,false) ;
00223
00224
00225
00226
00227
00228
00229
00230
00231 itsMarkerLogicalVolume->
00232 SetFieldManager(BDSGlobals->GetZeroFieldManager(),false);
00233
00234
00235
00236
00237 G4VisAttributes* VisAtt = new G4VisAttributes(G4Colour(0., 0., 0));
00238 VisAtt->SetForceSolid(true);
00239 itsInnerBPLogicalVolume->SetVisAttributes(VisAtt);
00240
00241 G4VisAttributes* VisAtt1 = new G4VisAttributes(G4Colour(0.4, 0.4, 0.4));
00242 VisAtt1->SetForceSolid(true);
00243 itsBeampipeLogicalVolume->SetVisAttributes(VisAtt1);
00244 }
00245
00246
00247 void BDSMultipole::BuildBPFieldMgr(G4MagIntegratorStepper* aStepper,
00248 G4MagneticField* aField)
00249 {
00250 itsChordFinder=
00251 new G4ChordFinder(aField,
00252 BDSGlobals->GetChordStepMinimum(),
00253 aStepper);
00254
00255 itsChordFinder->SetDeltaChord(BDSGlobals->GetDeltaChord());
00256
00257 itsBPFieldMgr= new G4FieldManager();
00258 itsBPFieldMgr->SetDetectorField(aField);
00259 itsBPFieldMgr->SetChordFinder(itsChordFinder);
00260 itsBPFieldMgr->SetDeltaIntersection(BDSGlobals->GetDeltaIntersection());
00261
00262 if(BDSGlobals->GetMinimumEpsilonStep()>0)
00263 itsBPFieldMgr->SetMinimumEpsilonStep(BDSGlobals->GetMinimumEpsilonStep());
00264
00265 if(BDSGlobals->GetMaximumEpsilonStep()>0)
00266 itsBPFieldMgr->SetMaximumEpsilonStep(BDSGlobals->GetMaximumEpsilonStep());
00267
00268 if(BDSGlobals->GetDeltaOneStep()>0)
00269 itsBPFieldMgr->SetDeltaOneStep(BDSGlobals->GetDeltaOneStep());
00270
00271 }
00272
00273
00274 void BDSMultipole::BuildDefaultMarkerLogicalVolume()
00275 {
00276 G4double xLength, yLength;
00277 xLength = yLength = std::max(itsOuterR,BDSGlobals->GetComponentBoxSize()/2);
00278
00279 if(DEBUG) G4cout<<"marker volume : x/y="<<xLength/m<<
00280 " m, l= "<< (itsLength+BDSGlobals->GetLengthSafety())/2/m <<" m"<<G4endl;
00281
00282 itsMarkerLogicalVolume=new G4LogicalVolume
00283 (new G4Box( itsName+"_solid",
00284 xLength,
00285 yLength,
00286 (itsLength+BDSGlobals->GetLengthSafety())/2),
00287 theMaterials->GetMaterial("Vacuum"),
00288 itsName+"_log");
00289
00290
00291
00292
00293
00294
00295
00296 }
00297
00298
00299 void BDSMultipole::BuildDefaultOuterLogicalVolume(G4double aLength,
00300 G4bool OuterMaterialIsVacuum)
00301 {
00302
00303
00304
00305
00306 G4double sagitta=0.;
00307
00308 G4Material* material;
00309 if(itsMaterial != "") material = theMaterials->GetMaterial(itsMaterial);
00310 else material = theMaterials->GetMaterial("Iron");
00311
00312 G4double outerRadius = itsOuterR;
00313 if(itsOuterR==0) outerRadius = BDSGlobals->GetComponentBoxSize()/2;
00314
00315 if(itsNSegments>1)
00316 {
00317 sagitta=itsLength/itsAngle*(1.-cos(itsAngle/2.));
00318 }
00319 if(OuterMaterialIsVacuum)
00320 {
00321 itsOuterLogicalVolume=
00322 new G4LogicalVolume(new G4Tubs(itsName+"_outer_solid",
00323 itsInnerIronRadius+sagitta,
00324 outerRadius,
00325 aLength/2,
00326 0,twopi*radian),
00327 theMaterials->GetMaterial("Vacuum"),
00328 itsName+"_outer_log");
00329 }
00330 if(!OuterMaterialIsVacuum)
00331 {
00332 itsOuterLogicalVolume=
00333 new G4LogicalVolume(new G4Tubs(itsName+"_outer_solid",
00334 itsInnerIronRadius+sagitta,
00335 outerRadius,
00336 aLength/2,
00337 0,twopi*radian),
00338 material,
00339 itsName+"_outer_log");
00340 }
00341
00342 G4RotationMatrix* Rot=NULL;
00343 if(itsAngle!=0 && itsType!="rbend") Rot=RotY90;
00344
00345 itsPhysiComp = new G4PVPlacement(
00346 Rot,
00347 0,
00348 itsOuterLogicalVolume,
00349 itsName+"_outer_phys",
00350 itsMarkerLogicalVolume,
00351 false,
00352 0);
00353
00354 itsOuterUserLimits =
00355 new G4UserLimits("multipole cut",aLength,DBL_MAX,DBL_MAX,
00356 BDSGlobals->GetThresholdCutCharged());
00357
00358 itsOuterLogicalVolume->SetUserLimits(itsOuterUserLimits);
00359
00360
00361
00362 }
00363
00364 void BDSMultipole::BuildOuterFieldManager(G4int nPoles, G4double poleField,
00365 G4double phiOffset)
00366 {
00367 if(nPoles<=0 || nPoles>10 || nPoles%2 !=0)
00368 G4Exception("BDSMultipole: Invalid number of poles");
00369 itsNPoles=nPoles;
00370 itsOuterFieldMgr=NULL;
00371 if (poleField==0) return;
00372
00373 itsOuterMagField=new BDSMultipoleOuterMagField(nPoles,poleField,phiOffset);
00374
00375 itsOuterFieldMgr=new G4FieldManager(itsOuterMagField);
00376
00377
00378
00379 itsOuterLogicalVolume->SetFieldManager(itsOuterFieldMgr,false);
00380
00381
00382 }
00383
00384
00385 BDSMultipole::~BDSMultipole()
00386 {
00387 if(itsPhysiComp) delete itsPhysiComp;
00388 if(itsBPFieldMgr) delete itsBPFieldMgr;
00389 if(itsBeampipeLogicalVolume) delete itsBeampipeLogicalVolume;
00390 if(itsBPTube) delete itsBPTube;
00391 if(itsChordFinder) delete itsChordFinder;
00392 if(itsOuterUserLimits) delete itsOuterUserLimits;
00393 if(itsBeampipeUserLimits) delete itsBeampipeUserLimits;
00394 if(itsOuterFieldMgr) delete itsOuterFieldMgr;
00395 if(itsOuterMagField) delete itsOuterMagField;
00396 if(itsSegRot)delete itsSegRot;
00397 }