00001
00002
00003
00004
00005
00006 const int DEBUG = 0;
00007
00008 #include "BDSGlobalConstants.hh"
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
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
00068
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());
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)
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());
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());
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());
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)
00168
00169 {
00170
00171
00172
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
00184
00185 G4double fieldBrr_r = ( (zhi-tempz)*itsBr_over_r[ilow] +
00186 (tempz-zlow)*itsBr_over_r[ilow+1]);
00187
00188
00189 G4double fieldBzz = ( (zhi-tempz)*itsBz[ilow] +
00190 (tempz-zlow)*itsBz[ilow+1]);
00191
00192 LocalB.setX(fieldBrr_r*(RLocalR.x()));
00193 LocalB.setY(fieldBrr_r*(RLocalR.y()));
00194 LocalB.setZ(fieldBzz);
00195
00196 LocalB.transform(rotation.inverse());
00197 }
00198
00199 if(inQuad) LocalB+=QuadB;
00200 if(inSext) LocalB+=SextB;
00201 if(inOct) LocalB+=OctB;
00202 if(inField) LocalB+=FieldB;
00203
00204
00205 Bfield[0] = LocalB.x();
00206 Bfield[1] = LocalB.y();
00207 Bfield[2] = LocalB.z();
00208
00209 Bfield[3] = 0;
00210 Bfield[4] = 0;
00211 Bfield[5] = 0;
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 if(DEBUG)
00227 {
00228 LocalB.rotateY(10e-3);
00229
00230
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
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
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 }