/home/cern/BDSIM_new/src/BDSMagFieldSQL.cc

00001 /* BDSIM code.    Version 1.0
00002    Author: Grahame A. Blair, Royal Holloway, Univ. of London.
00003    Last modified 25.12.2003
00004    Copyright (c) 2003 by G.A.Blair.  ALL RIGHTS RESERVED. 
00005 */
00006 const int DEBUG = 0;
00007 
00008 #include "BDSGlobalConstants.hh" // must be first in include list
00009 
00010 #include "BDSMagFieldSQL.hh"
00011 
00012 #include "G4Navigator.hh"
00013 #include "G4TransportationManager.hh"
00014 #include "G4RotationMatrix.hh"
00015 #include "G4VPhysicalVolume.hh"
00016 #include "G4TouchableHistoryHandle.hh"
00017 #include "G4TouchableHistory.hh"
00018 #include "G4NavigationHistory.hh"
00019 #include <string>
00020 #include <vector>
00021 
00022 using namespace std;
00023 
00024 BDSMagFieldSQL::BDSMagFieldSQL(const G4String& aFieldFile,
00025                                G4double aMarkerLength,
00026                                vector<G4String> Quadvol, vector<G4double> QuadBgrad,
00027                                vector<G4String> Sextvol, vector<G4double> SextBgrad,
00028                                vector<G4String> Octvol, vector<G4double> OctBgrad,
00029                                vector<G4String> Fieldvol, vector<G4ThreeVector> UniformField)
00030 
00031   :ifs(aFieldFile.c_str()),itsMarkerLength(aMarkerLength),FieldFile(aFieldFile),
00032    itsQuadBgrad(QuadBgrad), itsQuadVol(Quadvol),
00033    itsSextBgrad(SextBgrad), itsSextVol(Sextvol),
00034    itsOctBgrad(OctBgrad), itsOctVol(Octvol),
00035    itsUniformField(UniformField), itsFieldVol(Fieldvol)
00036 {
00037 }
00038 
00039 BDSMagFieldSQL::~BDSMagFieldSQL(){}
00040 
00041 void BDSMagFieldSQL::GetFieldValue( const G4double Point[4],
00042                        G4double *Bfield ) const
00043 {
00044   
00045   G4Navigator* IRNavigator=
00046     G4TransportationManager::GetTransportationManager()-> 
00047     GetNavigatorForTracking();
00048   // gab_dec03>>
00049   G4ThreeVector LocalR, GlobalR, LocalB, RLocalR, QuadB, SextB, OctB, FieldB;
00050   LocalR = GlobalR = LocalB = RLocalR = QuadB = SextB = OctB = FieldB= G4ThreeVector(0.,0.,0.);
00051   
00052   GlobalR.setX(Point[0]);
00053   GlobalR.setY(Point[1]);
00054   GlobalR.setZ(Point[2]);
00055 
00056   G4TouchableHistory* aTouchable = IRNavigator->CreateTouchableHistory();
00057   
00058   const G4NavigationHistory* itsHistory = aTouchable->GetHistory();
00059 
00060   const G4AffineTransform GlobalToMarker=itsHistory->GetTransform(1);
00061   const G4AffineTransform MarkerToGlobal=GlobalToMarker.Inverse();
00062   
00063   RLocalR=GlobalToMarker.TransformPoint(GlobalR);
00064   
00065   if( fabs(RLocalR.z()) > fabs(itsMarkerLength/2) )
00066     {
00067       // Outside of mokka region - field should be zero. This is needed
00068       // because sometimes RKStepper asks for overly large steps (1km)
00069       Bfield[0] = 0;
00070       Bfield[1] = 0;
00071       Bfield[2] = 0;
00072       Bfield[3] = 0;
00073       Bfield[4] = 0;
00074       Bfield[5] = 0;
00075       return;
00076       
00077     }
00078 
00079   G4AffineTransform GlobalAffine, LocalAffine;
00080   G4String VolName = aTouchable->GetVolume()->GetName();
00081   G4bool inQuad=false;
00082   G4bool inSext=false;
00083   G4bool inOct = false;
00084   G4bool inField=false;
00085 
00086   for(G4int i=0; i<(G4int)itsQuadVol.size(); i++)
00087     {
00088       if(VolName==itsQuadVol[i])
00089         {
00090           GlobalAffine=IRNavigator->GetGlobalToLocalTransform();
00091           LocalAffine=IRNavigator->GetLocalToGlobalTransform();
00092           LocalR=GlobalAffine.TransformPoint(GlobalR); 
00093           LocalR.setY(-LocalR.y());
00094           LocalR.setX(-LocalR.x());       // -ve signs because of Geant Co-ord System
00095           QuadB.setX(LocalR.y()*itsQuadBgrad[i]);
00096           QuadB.setY(LocalR.x()*itsQuadBgrad[i]);
00097           QuadB.setZ(0);
00098           QuadB = LocalAffine.TransformAxis(QuadB);
00099           inQuad=true;
00100           break;
00101         }
00102     }
00103   if(!inQuad) //i.e. if no quad found in previous check ^^^^^
00104     {
00105       for(G4int i=0; i<(G4int)itsSextVol.size(); i++)
00106         {
00107           if(VolName==itsSextVol[i])
00108             {
00109               GlobalAffine=IRNavigator->GetGlobalToLocalTransform();
00110               LocalAffine=IRNavigator->GetLocalToGlobalTransform();
00111               LocalR=GlobalAffine.TransformPoint(GlobalR); 
00112               LocalR.setY(-LocalR.y());
00113               LocalR.setX(-LocalR.x());   // -ve signs because of Geant Co-ord System
00114               SextB.setX(LocalR.x()*LocalR.y()*itsSextBgrad[i]);
00115               SextB.setY(-(LocalR.x()*LocalR.x()-LocalR.y()*LocalR.y())*itsSextBgrad[i]/2.);
00116               SextB.setZ(0.0);
00117               SextB = LocalAffine.TransformAxis(SextB);
00118               inSext=true;
00119               break;
00120             }
00121         }
00122     }
00123   
00124   if(!inSext && !inQuad)
00125     {
00126       for(G4int i=0; i<(G4int)itsOctVol.size(); i++)
00127         {
00128           if(VolName==itsOctVol[i])
00129             {
00130               GlobalAffine=IRNavigator->GetGlobalToLocalTransform();
00131               LocalAffine=IRNavigator->GetLocalToGlobalTransform();
00132               LocalR=GlobalAffine.TransformPoint(GlobalR); 
00133               LocalR.setY(-LocalR.y());
00134               LocalR.setX(-LocalR.x());   // -ve signs because of Geant Co-ord System
00135               OctB.setX( (3*LocalR.x()*LocalR.x()*LocalR.y() - 
00136                           LocalR.y()*LocalR.y()*LocalR.y())*itsOctBgrad[i]/6.);
00137               OctB.setY( (LocalR.x()*LocalR.x()*LocalR.x() -
00138                           LocalR.x()*LocalR.y()*LocalR.y())*itsOctBgrad[i]/6.);
00139               OctB.setZ(0.0);
00140               OctB = LocalAffine.TransformAxis(OctB);
00141               inOct=true;
00142                   break;
00143             }
00144         }
00145     }
00146     
00147   
00148   for(G4int i=0; i<(G4int)itsFieldVol.size(); i++)
00149     {
00150       if(VolName==itsFieldVol[i])
00151         {
00152           GlobalAffine=IRNavigator->GetGlobalToLocalTransform();
00153           LocalAffine=IRNavigator->GetLocalToGlobalTransform();
00154           LocalR=GlobalAffine.TransformPoint(GlobalR); 
00155           LocalR.setY(-LocalR.y());
00156           LocalR.setX(-LocalR.x());       // -ve signs because of Geant Co-ord System
00157           FieldB = itsUniformField[i];
00158           FieldB = LocalAffine.TransformAxis(FieldB);
00159           inField=true;
00160           break;
00161         }
00162     }
00163 
00164   if(itsMarkerLength>0) RLocalR.setZ(RLocalR.z()+itsMarkerLength/2);
00165   else RLocalR.setZ( -(RLocalR.z()+fabs(itsMarkerLength)/2) + fabs(itsMarkerLength));
00166   G4double tempz = RLocalR.z()/cm;
00167   if(tempz<0)  //Mokka region resets Z to be positive at starting from one
00168                //Edge of the region
00169     {
00170       // This should NEVER happen. If it does, then the cause is either that
00171       // the mokka region length is not set properly, or that the BDSRKStepper
00172       // is asking for a step length greater than the Mokka marker length
00173       G4cout << "Z position in Mokka region less than 0 - check step lengths!!" << G4endl;
00174       G4Exception("Quitting BDSIM in BDSMagFieldSQL.cc");
00175     }
00176   G4double zlow = floor(tempz);
00177   G4int ilow = (G4int)(zlow);
00178   G4double zhi = zlow + 1.0;
00179   if (ilow > (G4int)itsBz.size() ||
00180       itsBz.size()==0) LocalB = G4ThreeVector(0.,0.,0.);
00181   else
00182     {
00183       // Calculate the field local to MarkerVolume
00184       // Interpolate the value of the field nearest to the point
00185       G4double fieldBrr_r = ( (zhi-tempz)*itsBr_over_r[ilow] +
00186                               (tempz-zlow)*itsBr_over_r[ilow+1]);
00187       // then should divide by (zhi-zlow) but this = 1
00188       
00189       G4double fieldBzz = ( (zhi-tempz)*itsBz[ilow] +
00190                             (tempz-zlow)*itsBz[ilow+1]);
00191       // then should divide by (zhi-zlow) but this = 1
00192       LocalB.setX(fieldBrr_r*(RLocalR.x()));
00193       LocalB.setY(fieldBrr_r*(RLocalR.y()));
00194       LocalB.setZ(fieldBzz);
00195       // Now rotate to give BField on Global Reference Frame
00196       LocalB.transform(rotation.inverse());
00197     }
00198   //LocalB=G4ThreeVector(0.,0.,0.); //turn Bfield from Solenoid off
00199   if(inQuad) LocalB+=QuadB;
00200   if(inSext) LocalB+=SextB;
00201   if(inOct) LocalB+=OctB;
00202   if(inField) LocalB+=FieldB;
00203 
00204   // b-field
00205   Bfield[0] = LocalB.x();
00206   Bfield[1] = LocalB.y();
00207   Bfield[2] = LocalB.z();
00208   // e-field
00209   Bfield[3] = 0;
00210   Bfield[4] = 0;
00211   Bfield[5] = 0;
00212 
00213 
00214   /*
00215   G4cout << "BField: " << LocalB << G4endl;
00216   G4cout << itsMarkerLength << G4endl;
00217   G4cout << RLocalR << G4endl;
00218   G4cout << ilow << G4endl;
00219   G4cout << QuadB << G4endl;
00220   G4cout << SextB << G4endl;
00221   G4cout << OctB << G4endl;
00222   G4cout << G4endl;
00223   */
00224   
00225   
00226   if(DEBUG) 
00227     {
00228       LocalB.rotateY(10e-3); //to track from incoming beamline perspective
00229       // this needs the be the crossing angle plus any marker rotation applied
00230       // for IR solenoid case
00231       G4cout << RLocalR.x()/m << " "<<RLocalR.y()/m << " "<<RLocalR.z()/m << " "<< LocalB.x()/tesla << " " << LocalB.y()/tesla << " " << LocalB.z()/tesla << G4endl;
00232     }
00233   delete aTouchable;
00234   aTouchable = NULL;
00235 
00236 }
00237 
00238 void BDSMagFieldSQL::Prepare(G4VPhysicalVolume *referenceVolume)
00239 {
00240   if(FieldFile!="")
00241     {
00242       G4cout<<"BDSElement:: creating SQL field map"<<G4endl;
00243 
00244       if(!ifs)
00245         {
00246           G4cerr<<"\nBDSMagFieldSQL.cc: Unable to open Field Map File: " << FieldFile << G4endl;
00247           G4Exception("Aborting Program");
00248         }
00249       else
00250         G4cout << "Loading SQL Field Map file: " << FieldFile << G4endl;
00251       
00252       if(FieldFile.contains("inverse")) itsMarkerLength*=-1;
00253       double temp_z;
00254       double temp_Bz;
00255       double temp_solB;
00256       while(!ifs.eof()){
00257         if(FieldFile.contains("SiD"))
00258           ifs >> temp_z >> temp_Bz >> temp_solB;
00259         
00260         if(FieldFile.contains("LD"))
00261           ifs >> temp_z >> temp_Bz >> temp_solB >> temp_solB;
00262         
00263         if(FieldFile.contains("TESLA"))
00264           ifs >> temp_z >> temp_Bz;
00265         
00266         itsZ.push_back(temp_z*m);
00267         itsBz.push_back(temp_Bz*tesla);
00268       }
00269       
00270       itsdz = itsZ[1] - itsZ[0];
00271       
00272       //first element:
00273       itsdBz_by_dz.push_back( (itsBz[1] - itsBz[0]) / itsdz );
00274       itsBr_over_r.push_back(0.5 * itsdBz_by_dz[0] );
00275       
00276       for(G4int j=1; j<(G4int)itsBz.size()-2; j++)
00277         {
00278           itsdBz_by_dz.push_back( (itsBz[j+1] - itsBz[j-1]) / (2*itsdz) );
00279           itsBr_over_r.push_back(0.5 * itsdBz_by_dz[j] );
00280         }
00281       
00282       //last element:
00283       itsdBz_by_dz.push_back( (itsBz[itsBz.size()-1] - itsBz[itsBz.size()-2]) / itsdz );
00284       itsBr_over_r.push_back(0.5 * itsdBz_by_dz[itsdBz_by_dz.size()-1] );
00285     }
00286   
00287   SetOriginRotation(*(referenceVolume->GetFrameRotation()));
00288   SetOriginTranslation(referenceVolume->GetFrameTranslation());
00289 }

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