/home/cern/BDSIM_new/src/BDSElement.cc

00001 /* BDSIM code.    Version 1.0
00002    Author: John C. Carter, Royal Holloway, Univ. of London.
00003    Last modified 02.12.2004
00004    Copyright (c) 2004 by J.C.Carter.  ALL RIGHTS RESERVED. 
00005 */
00006 
00007 const int DEBUG = 0;
00008 
00009 #include "BDSGlobalConstants.hh" // must be first in include list
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 // geometry drivers
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   // WARNING: ALign in and out will only apply to the first instance of the
00061   //          element. Subsequent copies will have no alignement set.
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(); // build element box
00071       
00072       if(DEBUG) G4cout<<"BDSElement : end build logical volume "<<
00073                   itsName<<G4endl;
00074 
00075       PlaceComponents(geometry,bmap); // place components (from file) and build filed maps
00076     }
00077   else
00078     {
00079       (*LogVolCount)[itsName]++;
00080       
00081       itsMarkerLogicalVolume=(*LogVol)[itsName];
00082     }
00083 }
00084 
00085 void BDSElement::BuildGeometry()
00086 {
00087   // multiple element instances not implemented yet!!!
00088 
00089   // Build the logical volume 
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 // place components 
00118 void BDSElement::PlaceComponents(G4String geometry, G4String bmap)
00119 {
00120 
00121   G4String gFormat="", bFormat="";
00122   G4String gFile="", bFile="";
00123 
00124   // get geometry format and file
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   // get fieldmap format and file
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   // get the geometry for the driver
00156   // different drivers may interpret the fieldmap differently
00157   // so a field map without geometry is not allowed
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     // set sensitive volumes
00172     //vector<G4LogicalVolume*> SensComps = ggmad->SensitiveComponents;
00173     //for(G4int id=0; id<SensComps.size(); id++)
00174     //  SetMultipleSensitiveVolumes(SensComps[id]);
00175 
00176     
00177     SetMultipleSensitiveVolumes(itsMarkerLogicalVolume);
00178 
00179     // attach magnetic field if present
00180 
00181     if(bFormat=="XY")
00182       {
00183         itsField = new BDSXYMagField(bFile);
00184 
00185         // build the magnetic field manager and transportation
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     // attach magnetic field if present
00208 
00209     if(bFormat=="mokka" || bFormat=="none")
00210       {
00211         if(Mokka->HasFields || bFile!="")
00212           // Check for field file or volumes with fields
00213           // as there may be cases where there are no bFormats given
00214           // in gmad file but fields might be set to volumes in SQL files
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             // build the magnetic field manager and transportation
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   //   // test - dump field values
00240 //     G4cout<<"dumping field values..."<<G4endl;
00241 //     G4double Point[4];
00242 //     G4double BField[6];
00243 //     ofstream testf("fields.dat");
00244 
00245 //     for(G4double x=-1*m;x<1*m;x+=1*cm)
00246 //        for(G4double y=-1*m;y<1*m;y+=1*cm)
00247 //       for(G4double z=-1*m;z<1*m;z+=1*cm)
00248 //       {
00249 //      Point[0] = x;
00250 //      Point[1] = y;
00251 //      Point[2] = z;
00252 //      Point[3] = 0;
00253 //      itsField->GetFieldValue(Point,BField);
00254 //      testf<<Point[0]<<" "<<Point[1]<<" "<<Point[2]<<" "<<
00255 //        BField[0]<<" "<<BField[1]<<" "<<BField[2]<<G4endl;
00256 //       }
00257 
00258 //     testf.close();
00259 //     G4cout<<"done"<<G4endl;
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   //itsField = new BDSField();
00276 
00277   // Create an equation of motion for this field
00278   G4EqMagElectricField* fEquation = new G4EqMagElectricField(itsField);
00279 
00280   G4MagIntegratorStepper* fStepper = new G4ClassicalRK4( fEquation, nvar );
00281   //G4MagIntegratorStepper* fStepper = new BDSRK4Stepper( fEquation, nvar );
00282 
00283   // create a field manager
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 // creates a field mesh in the reference frame of a physical volume
00313 // from  b-field map value list 
00314 // has to be called after the component is placed in the geometry
00315 void BDSElement::PrepareField(G4VPhysicalVolume *referenceVolume)
00316 {
00317   if(!itsField) return;
00318   itsField->Prepare(referenceVolume);
00319 }
00320 
00321 // Rotates and positions the marker volume before it is placed in
00322 // BDSDetectorConstruction. It aligns the marker volume so that the
00323 // the beamline goes through the specified daugther volume (e.g. for mokka)
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           // advance co-ords in usual way if no alignment volumes found
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           //moving positioning to outgoing alignment volume
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           //moving position in Z be at least itsLength/2 away
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           // align outgoing (i.e. next component) to Marker Volume
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           //moving positioning to outgoing alignment volume
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           //moving position in Z be at least itsLength/2 away
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 }

Generated on Wed Mar 5 17:25:22 2008 for BDSIM by  doxygen 1.5.3