00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "BDSGlobalConstants.hh"
00019
00020 #include "BDSQuadrupole.hh"
00021 #include "G4Box.hh"
00022 #include "G4Tubs.hh"
00023 #include "G4VisAttributes.hh"
00024 #include "G4LogicalVolume.hh"
00025 #include "G4VPhysicalVolume.hh"
00026 #include "G4UserLimits.hh"
00027 #include "G4TransportationManager.hh"
00028
00029 #include <map>
00030
00031 const int DEBUG = 0;
00032
00033
00034
00035 typedef std::map<G4String,int> LogVolCountMap;
00036 extern LogVolCountMap* LogVolCount;
00037
00038 typedef std::map<G4String,G4LogicalVolume*> LogVolMap;
00039 extern LogVolMap* LogVol;
00040
00041 extern BDSMaterials* theMaterials;
00042
00043 extern G4RotationMatrix* RotY90;
00044
00045
00046 BDSQuadrupole::BDSQuadrupole(G4String aName, G4double aLength,
00047 G4double bpRad, G4double FeRad,
00048 G4double bGrad, G4double tilt, G4double outR,
00049 G4String aMaterial, G4String spec):
00050 BDSMultipole(aName, aLength, bpRad, FeRad, SetVisAttributes(), aMaterial),
00051 itsBGrad(bGrad)
00052 {
00053 if(DEBUG) G4cout<<"BDSQUADRUPOLE : SPEC : "<<spec<<G4endl;
00054
00055 G4String qtype = getParameterValueString(spec, "type");
00056 if(DEBUG) G4cout<<"qtype : "<<qtype<<G4endl;
00057
00058 SetOuterRadius(outR);
00059 itsTilt=tilt;
00060 itsType="quad";
00061
00062 if (!(*LogVolCount)[itsName])
00063 {
00064
00065
00066
00067 BuildDefaultMarkerLogicalVolume();
00068
00069
00070
00071
00072 BuildBPFieldAndStepper();
00073 BuildBPFieldMgr(itsStepper,itsMagField);
00074 BuildBeampipe(itsLength);
00075
00076
00077
00078
00079
00080 if(qtype=="standard")
00081 BuildOuterLogicalVolume();
00082 else if(qtype=="cylinder")
00083 BuildDefaultOuterLogicalVolume(itsLength);
00084 else
00085 BuildDefaultOuterLogicalVolume(itsLength);
00086 if(BDSGlobals->GetIncludeIronMagFields())
00087 {
00088 G4double polePos[4];
00089 G4double Bfield[3];
00090
00091
00092 polePos[0]=-BDSGlobals->GetMagnetPoleRadius()*sin(pi/4);
00093 polePos[1]=BDSGlobals->GetMagnetPoleRadius()*cos(pi/4);
00094 polePos[2]=0.;
00095 polePos[3]=-999.;
00096
00097 itsMagField->GetFieldValue(polePos,Bfield);
00098 G4double BFldIron=
00099 sqrt(Bfield[0]*Bfield[0]+Bfield[1]*Bfield[1])*
00100 BDSGlobals->GetMagnetPoleSize()/
00101 (BDSGlobals->GetComponentBoxSize()/2-
00102 BDSGlobals->GetMagnetPoleRadius());
00103
00104
00105 BFldIron/=2.;
00106
00107 BuildOuterFieldManager(4, BFldIron,pi/4);
00108 }
00109
00110
00111
00112
00113 SetMultipleSensitiveVolumes(itsBeampipeLogicalVolume);
00114 SetMultipleSensitiveVolumes(itsOuterLogicalVolume);
00115
00116
00117
00118
00119 itsVisAttributes=SetVisAttributes();
00120 itsVisAttributes->SetForceSolid(true);
00121 itsOuterLogicalVolume->SetVisAttributes(itsVisAttributes);
00122
00123
00124
00125
00126 (*LogVolCount)[itsName]=1;
00127 (*LogVol)[itsName]=itsMarkerLogicalVolume;
00128 }
00129 else
00130 {
00131 (*LogVolCount)[itsName]++;
00132 if(BDSGlobals->GetSynchRadOn()&& BDSGlobals->GetSynchRescale())
00133 {
00134
00135
00136
00137 itsName+=BDSGlobals->StringFromInt((*LogVolCount)[itsName]);
00138
00139
00140
00141
00142 BuildDefaultMarkerLogicalVolume();
00143
00144
00145
00146
00147 BuildBPFieldAndStepper();
00148 BuildBPFieldMgr(itsStepper,itsMagField);
00149 BuildBeampipe(itsLength);
00150
00151
00152
00153
00154
00155 if(qtype=="standard")
00156 BuildOuterLogicalVolume();
00157 else if(qtype=="cylinder")
00158 BuildDefaultOuterLogicalVolume(itsLength);
00159 else
00160 BuildDefaultOuterLogicalVolume(itsLength);
00161 if(BDSGlobals->GetIncludeIronMagFields())
00162 {
00163 G4double polePos[4];
00164 G4double Bfield[3];
00165
00166
00167 polePos[0]=-BDSGlobals->GetMagnetPoleRadius()*sin(pi/4);
00168 polePos[1]=BDSGlobals->GetMagnetPoleRadius()*cos(pi/4);
00169 polePos[2]=0.;
00170 polePos[3]=-999.;
00171
00172 itsMagField->GetFieldValue(polePos,Bfield);
00173 G4double BFldIron=
00174 sqrt(Bfield[0]*Bfield[0]+Bfield[1]*Bfield[1])*
00175 BDSGlobals->GetMagnetPoleSize()/
00176 (BDSGlobals->GetComponentBoxSize()/2-
00177 BDSGlobals->GetMagnetPoleRadius());
00178
00179
00180 BFldIron/=2.;
00181
00182 BuildOuterFieldManager(4, BFldIron,pi/4);
00183 }
00184
00185
00186
00187
00188
00189 SetSensitiveVolume(itsBeampipeLogicalVolume);
00190
00191
00192
00193
00194
00195 itsVisAttributes=SetVisAttributes();
00196 itsVisAttributes->SetForceSolid(true);
00197 itsOuterLogicalVolume->SetVisAttributes(itsVisAttributes);
00198
00199
00200
00201
00202 (*LogVol)[itsName]=itsMarkerLogicalVolume;
00203 }
00204 else
00205 {
00206
00207
00208
00209 itsMarkerLogicalVolume=(*LogVol)[itsName];
00210 }
00211 }
00212 }
00213
00214 void BDSQuadrupole::SynchRescale(G4double factor)
00215 {
00216 itsStepper->SetBGrad(factor*itsBGrad);
00217 itsMagField->SetBGrad(factor*itsBGrad);
00218 if(DEBUG) G4cout << "Quad " << itsName << " has been scaled" << G4endl;
00219 }
00220
00221 G4VisAttributes* BDSQuadrupole::SetVisAttributes()
00222 {
00223 itsVisAttributes=new G4VisAttributes(G4Colour(1,0,0));
00224 return itsVisAttributes;
00225 }
00226
00227 void BDSQuadrupole::BuildBPFieldAndStepper()
00228 {
00229
00230 itsMagField=new BDSQuadMagField(itsBGrad);
00231 itsEqRhs=new G4Mag_UsualEqRhs(itsMagField);
00232
00233 itsStepper=new BDSQuadStepper(itsEqRhs);
00234 itsStepper->SetBGrad(itsBGrad);
00235 }
00236
00237 void BDSQuadrupole::BuildOuterLogicalVolume()
00238 {
00239 G4double outerRadius = itsOuterR;
00240 if(itsOuterR==0) outerRadius = BDSGlobals->GetComponentBoxSize()/2;
00241
00242 itsOuterLogicalVolume=
00243 new G4LogicalVolume(new G4Tubs(itsName+"_outer_solid",
00244 itsInnerIronRadius,
00245 outerRadius * sqrt(2.0),
00246 itsLength/2,
00247 0,twopi*radian),
00248 theMaterials->GetMaterial("Vacuum"),
00249 itsName+"_outer");
00250
00251
00252 G4LogicalVolume* lQuadrant =
00253 new G4LogicalVolume(new G4Tubs(itsName+"_outer_solid",
00254 itsInnerIronRadius,
00255 outerRadius * sqrt(2.0),
00256 itsLength/2,
00257 0,pi/ 2 *radian),
00258 theMaterials->GetMaterial("Vacuum"),
00259 itsName+"_outer");
00260
00261
00262 G4double poleR = itsBpRadius;
00263 G4double phiStart = -pi / 4;
00264 G4double dPhi = pi / 2;
00265
00266 G4LogicalVolume* lPole =
00267 new G4LogicalVolume(new G4Tubs(itsName+"_pole",
00268 0,
00269 poleR,
00270 itsLength/2,
00271 phiStart,
00272 dPhi),
00273 theMaterials->GetMaterial("Iron"),
00274 itsName+"pole_outer");
00275
00276 G4RotationMatrix* rotPole = new G4RotationMatrix;
00277
00278 rotPole->rotateZ(3.*pi / 4.);
00279
00280 G4double xPole = (poleR + itsBpRadius) / sqrt(2.0);
00281 G4double yPole = (poleR + itsBpRadius) / sqrt(2.0);
00282
00283
00284 G4VPhysicalVolume* itsPhysiQPole1;
00285 itsPhysiQPole1 = new G4PVPlacement(
00286 rotPole,
00287 G4ThreeVector(xPole,yPole,0),
00288 lPole,
00289 itsName+"_solid",
00290 lQuadrant,
00291 false,
00292 0);
00293
00294
00295 G4VisAttributes* VisAtt =
00296 new G4VisAttributes(G4Colour(1., 0., 0.));
00297 VisAtt->SetForceSolid(true);
00298 lPole->SetVisAttributes(VisAtt);
00299
00300
00301
00302 G4double rYoke = itsOuterR - poleR - itsBpRadius + poleR * cos(dPhi / 2);
00303
00304 if(rYoke > 0 )
00305 {
00306
00307
00308 G4double rYoke1 = itsOuterR;
00309 G4double rYoke2 = itsBpRadius;
00310
00311 G4LogicalVolume* lYoke1 =
00312 new G4LogicalVolume(new G4Trd(itsName+"_yoke1",
00313 rYoke1 / 2,
00314 rYoke2 / 2,
00315 itsLength/2,
00316 itsLength/2,
00317 rYoke/2),
00318 theMaterials->GetMaterial("Iron"),
00319 itsName+"yoke_outer1");
00320
00321 G4RotationMatrix* rotYoke = new G4RotationMatrix;
00322
00323 rotYoke->rotateX( - pi / 2.);
00324 rotYoke->rotateY( pi / 4.);
00325
00326 G4double xYoke = (poleR - poleR * cos(dPhi / 2) + itsBpRadius + rYoke/2) / sqrt(2.0);
00327 G4double yYoke = (poleR - poleR * cos(dPhi / 2) + itsBpRadius + rYoke/2) / sqrt(2.0);
00328
00329
00330 G4VPhysicalVolume* itsPhysiQYoke1;
00331 itsPhysiQYoke1 = new G4PVPlacement(
00332 rotYoke,
00333 G4ThreeVector(xYoke,yYoke,0),
00334 lYoke1,
00335 itsName+"_yoke_solid",
00336 lQuadrant,
00337 false,
00338 0);
00339
00340
00341 G4VisAttributes* VisAtt1 =
00342 new G4VisAttributes(G4Colour(1., 0., 0.4));
00343 VisAtt1->SetForceSolid(true);
00344 lYoke1->SetVisAttributes(VisAtt1);
00345 }
00346 else
00347 {
00348 G4cerr<<"Not enough place for yoke..."<<G4endl;
00349 }
00350
00351
00352
00353
00354
00355 G4VPhysicalVolume* itsPhysiQuadrant1;
00356 itsPhysiQuadrant1 = new G4PVPlacement(
00357 NULL,
00358 0,
00359 lQuadrant,
00360 itsName+"_solid",
00361 itsOuterLogicalVolume,
00362 false,
00363 0);
00364
00365 G4RotationMatrix* rotQ2= new G4RotationMatrix;
00366 rotQ2->rotateZ( pi / 2.);
00367
00368 G4VPhysicalVolume* itsPhysiQuadrant2;
00369 itsPhysiQuadrant2 = new G4PVPlacement(
00370 rotQ2,
00371 0,
00372 lQuadrant,
00373 itsName+"_solid",
00374 itsOuterLogicalVolume,
00375 false,
00376 0);
00377
00378 G4RotationMatrix* rotQ3= new G4RotationMatrix;
00379 rotQ3->rotateZ( pi );
00380
00381 G4VPhysicalVolume* itsPhysiQuadrant3;
00382 itsPhysiQuadrant3 = new G4PVPlacement(
00383 rotQ3,
00384 0,
00385 lQuadrant,
00386 itsName+"_solid",
00387 itsOuterLogicalVolume,
00388 false,
00389 0);
00390
00391
00392 G4RotationMatrix* rotQ4= new G4RotationMatrix;
00393 rotQ4->rotateZ( 3. * pi / 2.);
00394
00395 G4VPhysicalVolume* itsPhysiQuadrant4;
00396 itsPhysiQuadrant4 = new G4PVPlacement(
00397 rotQ4,
00398 0,
00399 lQuadrant,
00400 itsName+"_solid",
00401 itsOuterLogicalVolume,
00402 false,
00403 0);
00404
00405
00406
00407
00408
00409
00410 itsPhysiComp =
00411 new G4PVPlacement(
00412 0,
00413 0,
00414 itsOuterLogicalVolume,
00415 itsName+"_outer_phys",
00416 itsMarkerLogicalVolume,
00417 false,
00418 0);
00419
00420 itsOuterUserLimits =
00421 new G4UserLimits("quadrupole cut",itsLength,DBL_MAX,DBL_MAX,
00422 BDSGlobals->GetThresholdCutCharged());
00423
00424 itsOuterLogicalVolume->SetUserLimits(itsOuterUserLimits);
00425 }
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635 BDSQuadrupole::~BDSQuadrupole()
00636 {
00637 delete itsVisAttributes;
00638 delete itsMarkerLogicalVolume;
00639 delete itsOuterLogicalVolume;
00640 delete itsPhysiComp;
00641 delete itsMagField;
00642 delete itsEqRhs;
00643 delete itsStepper;
00644 }