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

Generated on 28 Jun 2015 for BDSIM by  doxygen 1.4.7