00001
00002
00003
00004
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
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
00066
00067
00068
00069 itsIRNavigator->SetWorldVolume(G4TransportationManager::GetTransportationManager()->GetNavigatorForTracking()->GetWorldVolume());
00070
00071 G4ThreeVector LocalR, LocalB, RLocalR, FieldB, NPoleB, GlobalR(Point[0], Point[1], Point[2]);
00072
00073
00074
00075
00076 itsIRNavigator->LocateGlobalPointAndSetup(GlobalR);
00077
00078 G4TouchableHistoryHandle aTouchable = itsIRNavigator->CreateTouchableHistoryHandle();
00079 const G4AffineTransform GlobalToMarker=aTouchable->GetHistory()->GetTransform(1);
00080
00081 RLocalR=GlobalToMarker.TransformPoint(GlobalR);
00082
00083 if( fabs(RLocalR.z()) > fabs(itsMarkerLength/2) ){
00084
00085
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());
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.);
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)
00145
00146 {
00147
00148
00149
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
00161
00162 G4double fieldBrr_r = ( (zhi-tempz)*itsBr_over_r[ilow] +
00163 (tempz-zlow)*itsBr_over_r[ilow+1]);
00164
00165
00166 G4double fieldBzz = ( (zhi-tempz)*itsBz[ilow] +
00167 (tempz-zlow)*itsBz[ilow+1]);
00168
00169 LocalB.setX(fieldBrr_r*(RLocalR.x()));
00170 LocalB.setY(fieldBrr_r*(RLocalR.y()));
00171 LocalB.setZ(fieldBzz);
00172
00173 LocalB.transform(Rotation().inverse());
00174 }
00175
00176 }
00177
00178 if(inField) LocalB+=FieldB;
00179 if(inNPole) LocalB+=NPoleB;
00180
00181 Bfield[0] = LocalB.x();
00182 Bfield[1] = LocalB.y();
00183 Bfield[2] = LocalB.z();
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 #ifdef BDSDEBUG
00198 LocalB.rotateY(10e-3);
00199
00200
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
00204
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
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
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 }