00001
00002
00003
00004
00005
00006
00007 const int DEBUG = 0;
00008
00009 #include "BDSGlobalConstants.hh"
00010 #include "BDSElement.hh"
00011 #include "G4Box.hh"
00012 #include "G4Tubs.hh"
00013 #include "G4Torus.hh"
00014 #include "G4Trd.hh"
00015 #include "G4VisAttributes.hh"
00016 #include "G4LogicalVolume.hh"
00017 #include "G4VPhysicalVolume.hh"
00018 #include "G4PVPlacement.hh"
00019 #include "G4UserLimits.hh"
00020 #include "G4Mag_UsualEqRhs.hh"
00021
00022 #include "BDSAcceleratorComponent.hh"
00023
00024
00025 #include "ggmad.hh"
00026 #include "BDSGeometrySQL.hh"
00027
00028 #ifdef USE_XML
00029 #include "BDSGeometryGDML.hh"
00030 #endif
00031
00032 #include <map>
00033
00034 using namespace std;
00035
00036
00037
00038 typedef std::map<G4String,int> LogVolCountMap;
00039 extern LogVolCountMap* LogVolCount;
00040
00041 typedef std::map<G4String,G4LogicalVolume*> LogVolMap;
00042 extern LogVolMap* LogVol;
00043
00044 extern BDSMaterials* theMaterials;
00045 extern G4RotationMatrix* RotY90;
00046
00047
00048
00049 BDSElement::BDSElement(G4String aName, G4String geometry, G4String bmap,
00050 G4double aLength, G4double bpRad, G4double outR):
00051 BDSAcceleratorComponent(
00052 aName,
00053 aLength,bpRad,0,0,
00054 SetVisAttributes()),
00055 itsField(NULL)
00056 {
00057 itsOuterR = outR;
00058 SetType(_ELEMENT);
00059
00060
00061
00062 align_in_volume = NULL;
00063 align_out_volume = NULL;
00064
00065 if(!(*LogVolCount)[itsName])
00066 {
00067 if(DEBUG) G4cout<<"BDSElement : starting build logical volume "<<
00068 itsName<<G4endl;
00069
00070 BuildGeometry();
00071
00072 if(DEBUG) G4cout<<"BDSElement : end build logical volume "<<
00073 itsName<<G4endl;
00074
00075 PlaceComponents(geometry,bmap);
00076 }
00077 else
00078 {
00079 (*LogVolCount)[itsName]++;
00080
00081 itsMarkerLogicalVolume=(*LogVol)[itsName];
00082 }
00083 }
00084
00085 void BDSElement::BuildGeometry()
00086 {
00087
00088
00089
00090
00091 if(DEBUG) G4cout<<"BDSElement : creating logical volume"<<G4endl;
00092 G4double elementSizeX=itsOuterR, elementSizeY = itsOuterR;
00093 if(itsOuterR==0)
00094 {
00095 elementSizeX =BDSGlobals->GetTunnelRadius() / 2;
00096 elementSizeY =BDSGlobals->GetTunnelRadius() / 2;
00097 }
00098
00099 itsMarkerLogicalVolume =
00100 new G4LogicalVolume(new G4Box(itsName+"generic_element",
00101 elementSizeX,
00102 elementSizeY,
00103 itsLength/2),
00104 theMaterials->GetMaterial("Vacuum"),
00105 itsName);
00106
00107 (*LogVolCount)[itsName] = 1;
00108 (*LogVol)[itsName] = itsMarkerLogicalVolume;
00109
00110 itsOuterUserLimits = new G4UserLimits();
00111 itsOuterUserLimits->SetMaxAllowedStep(itsLength);
00112 itsMarkerLogicalVolume->SetUserLimits(itsOuterUserLimits);
00113
00114
00115 }
00116
00117
00118 void BDSElement::PlaceComponents(G4String geometry, G4String bmap)
00119 {
00120
00121 G4String gFormat="", bFormat="";
00122 G4String gFile="", bFile="";
00123
00124
00125 G4int pos = geometry.find(":");
00126
00127 if(pos<0) {
00128 G4cerr<<"WARNING: invalid geometry reference format : "<<geometry<<endl;
00129 gFormat="none";
00130 }
00131 else {
00132 gFormat = geometry.substr(0,pos);
00133 gFile = geometry.substr(pos+1,geometry.length() - pos);
00134 }
00135
00136
00137 pos = bmap.find(":");
00138
00139 if(pos<0) {
00140 G4cerr<<"WARNING: invalid B map reference format : "<<bmap<<endl;
00141 bFormat="none";
00142 }
00143 else {
00144 bFormat = bmap.substr(0,pos);
00145 bFile = bmap.substr(pos+1,bmap.length() - pos);
00146 }
00147
00148 G4cout<<"placing components\n: geometry format - "<<gFormat<<G4endl<<
00149 "file - "<<gFile<<G4endl;
00150
00151 G4cout<<"bmap format - "<<bFormat<<G4endl<<
00152 "file - "<<bFile<<G4endl;
00153
00154
00155
00156
00157
00158
00159 GGmadDriver *ggmad;
00160 BDSGeometrySQL *Mokka;
00161
00162 #ifdef USE_XML
00163 BDSGeometryGDML *LCDD;
00164 #endif
00165
00166 if(gFormat=="gmad") {
00167
00168 ggmad = new GGmadDriver(gFile);
00169 ggmad->Construct(itsMarkerLogicalVolume);
00170
00171
00172
00173
00174
00175
00176
00177 SetMultipleSensitiveVolumes(itsMarkerLogicalVolume);
00178
00179
00180
00181 if(bFormat=="XY")
00182 {
00183 itsField = new BDSXYMagField(bFile);
00184
00185
00186 BuildMagField();
00187 }
00188 }
00189 else if(gFormat=="lcdd") {
00190 #ifdef USE_XML
00191 LCDD = new BDSGeometryGDML(gFile);
00192 LCDD->Construct(itsMarkerLogicalVolume);
00193 #else
00194 G4cout << "XML support not selected during BDSIM configuration" << G4endl;
00195 G4Exception("Please re-compile BDSIM with USE_XML flag in Makefile");
00196 #endif
00197 }
00198 else if(gFormat=="mokka") {
00199
00200 Mokka = new BDSGeometrySQL(gFile,itsLength);
00201 Mokka->Construct(itsMarkerLogicalVolume);
00202 vector<G4LogicalVolume*> SensComps = Mokka->SensitiveComponents;
00203 for(G4int id=0; id<(G4int)SensComps.size(); id++)
00204 SetMultipleSensitiveVolumes(SensComps[id]);
00205 align_in_volume = Mokka->align_in_volume;
00206 align_out_volume = Mokka->align_out_volume;
00207
00208
00209 if(bFormat=="mokka" || bFormat=="none")
00210 {
00211 if(Mokka->HasFields || bFile!="")
00212
00213
00214
00215 {
00216 itsField = new BDSMagFieldSQL(bFile,itsLength,
00217 Mokka->Quadvol, Mokka->QuadBgrad,
00218 Mokka->Sextvol, Mokka->SextBgrad,
00219 Mokka->Octvol, Mokka->OctBgrad,
00220 Mokka->Fieldvol,Mokka->UniformField);
00221
00222
00223 BuildMagField(6,true);
00224 }
00225 }
00226 }
00227 else if(gFormat=="gdml") {
00228
00229 G4cout<<"GDML.... sorry, not implemented yet..."<<G4endl;
00230
00231 }
00232 else {
00233 G4cerr<<"geometry format "<<gFormat<<" not supported"<<G4endl;
00234 }
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 }
00263
00264
00265
00266 G4VisAttributes* BDSElement::SetVisAttributes()
00267 {
00268 itsVisAttributes=new G4VisAttributes(G4Colour(0.5,0.5,1));
00269 return itsVisAttributes;
00270 }
00271
00272
00273 void BDSElement::BuildMagField(G4int nvar, G4bool forceToAllDaughters)
00274 {
00275
00276
00277
00278 G4EqMagElectricField* fEquation = new G4EqMagElectricField(itsField);
00279
00280 G4MagIntegratorStepper* fStepper = new G4ClassicalRK4( fEquation, nvar );
00281
00282
00283
00284 G4FieldManager* fieldManager = new G4FieldManager();
00285 fieldManager->SetDetectorField(itsField );
00286
00287
00288 G4double fMinStep = BDSGlobals->GetChordStepMinimum();
00289
00290 G4MagInt_Driver* fIntgrDriver = new G4MagInt_Driver(fMinStep,
00291 fStepper,
00292 fStepper->GetNumberOfVariables() );
00293
00294 G4ChordFinder* fChordFinder = new G4ChordFinder(fIntgrDriver);
00295
00296 fChordFinder->SetDeltaChord(BDSGlobals->GetDeltaChord());
00297
00298 fieldManager->SetChordFinder( fChordFinder );
00299
00300 itsMarkerLogicalVolume->SetFieldManager(fieldManager,forceToAllDaughters);
00301
00302 G4UserLimits* fUserLimits =
00303 new G4UserLimits("element cuts",DBL_MAX,DBL_MAX,DBL_MAX,
00304 BDSGlobals->GetThresholdCutCharged());
00305
00306 fUserLimits->SetMaxAllowedStep(1e-2 * m);
00307
00308 itsMarkerLogicalVolume->SetUserLimits(fUserLimits);
00309
00310 }
00311
00312
00313
00314
00315 void BDSElement::PrepareField(G4VPhysicalVolume *referenceVolume)
00316 {
00317 if(!itsField) return;
00318 itsField->Prepare(referenceVolume);
00319 }
00320
00321
00322
00323
00324 void BDSElement::AlignComponent(G4ThreeVector& TargetPos,
00325 G4RotationMatrix *TargetRot,
00326 G4RotationMatrix& globalRotation,
00327 G4ThreeVector& rtot,
00328 G4ThreeVector& rlast,
00329 G4ThreeVector& localX,
00330 G4ThreeVector& localY,
00331 G4ThreeVector& localZ)
00332 {
00333
00334
00335 if(align_in_volume == NULL)
00336 {
00337 if(align_out_volume == NULL)
00338 {
00339
00340
00341 rtot = rlast + localZ*(itsLength/2 + BDSGlobals->GetLengthSafety()/2);
00342 rlast = rtot + localZ*(itsLength/2 + BDSGlobals->GetLengthSafety()/2);
00343 return;
00344 }
00345 else
00346 {
00347 G4cout << "BDSElement : Aligning outgoing to SQL element "
00348 << align_out_volume->GetName() << G4endl;
00349 G4RotationMatrix Trot = *TargetRot;
00350 G4RotationMatrix trackedRot;
00351 G4RotationMatrix outRot = *(align_out_volume->GetFrameRotation());
00352 trackedRot.transform(outRot.inverse());
00353 trackedRot.transform(Trot.inverse());
00354 globalRotation = trackedRot;
00355
00356 G4ThreeVector outPos = align_out_volume->GetFrameTranslation();
00357 G4ThreeVector diff = outPos;
00358
00359 G4ThreeVector zHalfAngle = G4ThreeVector(0.,0.,1.);
00360
00361 zHalfAngle.transform(globalRotation);
00362
00363
00364 rlast = TargetPos - ((outPos.unit()).transform(Trot.inverse()) )*diff.mag();
00365 localX.transform(outRot.inverse());
00366 localY.transform(outRot.inverse());
00367 localZ.transform(outRot.inverse());
00368
00369 localX.transform(Trot.inverse());
00370 localY.transform(Trot.inverse());
00371 localZ.transform(Trot.inverse());
00372
00373
00374 rlast +=zHalfAngle*(itsLength/2 + diff.z() + BDSGlobals->GetLengthSafety()/2);
00375 return;
00376 }
00377 }
00378
00379 if(align_in_volume != NULL)
00380 {
00381 G4cout << "BDSElement : Aligning incoming to SQL element "
00382 << align_in_volume->GetName() << G4endl;
00383
00384 const G4RotationMatrix* inRot = align_in_volume->GetFrameRotation();
00385 TargetRot->transform((*inRot).inverse());
00386
00387 G4ThreeVector inPos = align_in_volume->GetFrameTranslation();
00388 inPos.transform((*TargetRot).inverse());
00389 TargetPos+=G4ThreeVector(inPos.x(), inPos.y(), 0.0);
00390
00391 if(align_out_volume == NULL)
00392 {
00393
00394
00395 G4RotationMatrix Trot = *TargetRot;
00396 globalRotation.transform(Trot.inverse());
00397
00398 G4ThreeVector zHalfAngle = G4ThreeVector(0.,0.,1.);
00399 zHalfAngle.transform(Trot.inverse());
00400
00401 rlast = TargetPos + zHalfAngle*(itsLength/2 + BDSGlobals->GetLengthSafety()/2);
00402 localX.transform(Trot.inverse());
00403 localY.transform(Trot.inverse());
00404 localZ.transform(Trot.inverse());
00405 return;
00406 }
00407
00408 else
00409 {
00410 G4cout << "BDSElement : Aligning outgoing to SQL element "
00411 << align_out_volume->GetName() << G4endl;
00412 G4RotationMatrix Trot = *TargetRot;
00413 G4RotationMatrix trackedRot;
00414 G4RotationMatrix outRot = *(align_out_volume->GetFrameRotation());
00415 trackedRot.transform(outRot.inverse());
00416 trackedRot.transform(Trot.inverse());
00417 globalRotation = trackedRot;
00418
00419 G4ThreeVector outPos = align_out_volume->GetFrameTranslation();
00420 G4ThreeVector diff = outPos;
00421
00422 G4ThreeVector zHalfAngle = G4ThreeVector(0.,0.,1.);
00423
00424 zHalfAngle.transform(globalRotation);
00425
00426
00427 rlast = TargetPos - ((outPos.unit()).transform(Trot.inverse()) )*diff.mag();
00428 localX.transform(outRot.inverse());
00429 localY.transform(outRot.inverse());
00430 localZ.transform(outRot.inverse());
00431
00432 localX.transform(Trot.inverse());
00433 localY.transform(Trot.inverse());
00434 localZ.transform(Trot.inverse());
00435
00436
00437 rlast +=zHalfAngle*(itsLength/2 + diff.z() + BDSGlobals->GetLengthSafety()/2);
00438 return;
00439 }
00440 }
00441
00442 }
00443
00444 BDSElement::~BDSElement()
00445 {
00446
00447 delete itsVisAttributes;
00448
00449 }