CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/MagneticField/Interpolation/src/TrapezoidalCartesianMFGrid.cc

Go to the documentation of this file.
00001 
00008 #include "TrapezoidalCartesianMFGrid.h"
00009 #include "binary_ifstream.h"
00010 #include "LinearGridInterpolator3D.h"
00011 #include "MagneticField/VolumeGeometry/interface/MagExceptions.h"
00012 #include <iostream>
00013 
00014 //#define DEBUG_GRID
00015 
00016 using namespace std;
00017 
00018 TrapezoidalCartesianMFGrid::TrapezoidalCartesianMFGrid( binary_ifstream& inFile,
00019                                                         const GloballyPositioned<float>& vol)
00020   : MFGrid3D(vol), increasingAlongX(false), convertToLocal(true)
00021 {
00022   
00023   // The parameters read from the data files are given in global coordinates.
00024   // In version 85l, local frame has the same orientation of global frame for the reference
00025   // volume, i.e. the r.f. transformation is only a translation.
00026   // There is therefore no need to convert the field values to local coordinates.
00027 
00028   // Check orientation of local reference frame: 
00029   GlobalVector localXDir(frame().toGlobal(LocalVector(1,0,0)));
00030   GlobalVector localYDir(frame().toGlobal(LocalVector(0,1,0)));
00031 
00032   if (localXDir.dot(GlobalVector(1,0,0)) > 0.999999 &&
00033       localYDir.dot(GlobalVector(0,1,0)) > 0.999999) {
00034     // "null" rotation - requires no conversion...
00035     convertToLocal = false;
00036   } else if (localXDir.dot(GlobalVector(0,1,0)) > 0.999999 &&
00037              localYDir.dot(GlobalVector(1,0,0)) > 0.999999) {
00038     // Typical orientation if master volume is in sector 1 
00039     convertToLocal = true;    
00040   } else {
00041     convertToLocal = true;    
00042     // Nothing wrong in principle, but this is not expected
00043     cout << "WARNING: TrapezoidalCartesianMFGrid: unexpected orientation: x: " 
00044          << localXDir << " y: " << localYDir << endl;
00045   }
00046 
00047   int n1, n2, n3;
00048   inFile >> n1 >> n2 >> n3;
00049   double xref, yref, zref;
00050   inFile >> xref >> yref >> zref;
00051   double step1, step2, step3;
00052   inFile >> step1    >> step2    >> step3;
00053 
00054   double BasicDistance1[3][3];  // linear step
00055   double BasicDistance2[3][3];  // linear offset
00056   bool   easya, easyb, easyc;
00057 
00058   inFile >> BasicDistance1[0][0] >> BasicDistance1[1][0] >> BasicDistance1[2][0];
00059   inFile >> BasicDistance1[0][1] >> BasicDistance1[1][1] >> BasicDistance1[2][1];
00060   inFile >> BasicDistance1[0][2] >> BasicDistance1[1][2] >> BasicDistance1[2][2];
00061   inFile >> BasicDistance2[0][0] >> BasicDistance2[1][0] >> BasicDistance2[2][0];
00062   inFile >> BasicDistance2[0][1] >> BasicDistance2[1][1] >> BasicDistance2[2][1];
00063   inFile >> BasicDistance2[0][2] >> BasicDistance2[1][2] >> BasicDistance2[2][2];
00064   inFile >> easya >> easyb >> easyc;
00065 
00066   vector<BVector> fieldValues;
00067   float Bx, By, Bz;
00068   int nLines = n1*n2*n3;
00069   fieldValues.reserve(nLines);
00070   for (int iLine=0; iLine<nLines; ++iLine){
00071     inFile >> Bx >> By >> Bz;
00072     if (convertToLocal) {
00073       // Preserve double precision!
00074       Vector3DBase<double, LocalTag>  lB = frame().toLocal(Vector3DBase<double, GlobalTag>(Bx,By,Bz));
00075       fieldValues.push_back(BVector(lB.x(), lB.y(), lB.z()));
00076       
00077     } else {
00078       fieldValues.push_back(BVector(Bx,By,Bz));
00079     }
00080   }
00081   // check completeness
00082   string lastEntry;
00083   inFile >> lastEntry;
00084   if (lastEntry != "complete") {
00085     cout << "ERROR during file reading: file is not complete" << endl;
00086   }
00087 
00088   // In version 1103l the reference sector is at phi=0 so that local y is along global X.
00089   // The increasing grid steps for the same volume are then along Y instead than along X.
00090   // To use Trapezoid2RectangleMappingX to map the trapezoidal geometry to a rectangular
00091   // cartesian geometry, we have to exchange (global) X and Y appropriately when constructing
00092   // it.
00093   int nx, ny;
00094   double stepx, stepy, stepz;
00095   double dstep, offset;
00096   if (!easya && easyb && easyc) {
00097     // Increasing grid spacing is on x
00098     increasingAlongX = true;
00099     nx = n1;
00100     ny = n2;
00101     stepx = step1; 
00102     stepy = step2;
00103     stepz = step3;
00104     dstep = BasicDistance1[0][1];
00105     offset = BasicDistance2[0][1];
00106   } else if (easya && !easyb && easyc) {
00107     // Increasing grid spacing is on y
00108     increasingAlongX = false;
00109     nx = n2;
00110     ny = n1;
00111     stepx = step2; 
00112     stepy = step1;
00113     stepz = -step3;
00114     dstep = BasicDistance1[1][0];
00115     offset = BasicDistance2[1][0];
00116 
00117    } else {
00118     // Increasing spacing on z or on > 1 coordinate not supported
00119     throw MagGeometryError("TrapezoidalCartesianMFGrid only implemented for first or second coordinate");
00120   }
00121 
00122   double a = stepx * (nx -1);             // first base
00123   double b = a + dstep * (ny-1) * (nx-1); // second base
00124   double h = stepy * (ny-1);              // height
00125   double delta = -offset * (ny-1);        // offset between two bases
00126   double baMinus1 = dstep*(ny-1) / stepx; // (b*a) - 1
00127 
00128   GlobalPoint grefp( xref, yref, zref);
00129   LocalPoint lrefp = frame().toLocal( grefp);
00130 
00131   if (fabs(baMinus1) > 0.000001) {
00132     double b_over_a = 1 + baMinus1;
00133     double a1 = delta/baMinus1;
00134 
00135 #ifdef DEBUG_GRID
00136     cout << "Trapeze size (a,b,h) = " << a << "," << b << "," << h << endl;
00137     cout << "Global origin " << grefp << endl;
00138     cout << "Local origin  " << lrefp << endl;
00139     cout << "a1 = " << a1 << endl;
00140 #endif
00141 
00142     // FIXME ASSUMPTION: here we assume that the local reference frame is oriented with X along 
00143     // the direction of where the grid is not uniform. This is the case for all current geometries
00144     double x0 = lrefp.x() + a1;
00145     double y0 = lrefp.y() + h/2.;
00146     mapping_ = Trapezoid2RectangleMappingX( x0, y0, b_over_a, h);
00147   }
00148   else { // parallelogram
00149     mapping_ = Trapezoid2RectangleMappingX( 0, 0, delta/h);
00150   }
00151 
00152   // transform reference point to grid frame
00153   double xrec, yrec;
00154   mapping_.rectangle( lrefp.x(), lrefp.y(), xrec, yrec);
00155 
00156   Grid1D gridX( xrec, xrec + (a+b)/2., nx);
00157   Grid1D gridY( yrec, yrec + h, ny);
00158   Grid1D gridZ( lrefp.z(), lrefp.z() + stepz*(n3-1), n3);  
00159 
00160 #ifdef DEBUG_GRID
00161   cout << " GRID X range: local " << gridX.lower() <<  " - " << gridX.upper()
00162        <<" global: " << (frame().toGlobal(LocalPoint(gridX.lower(),0,0))).y() << " - " 
00163        << (frame().toGlobal(LocalPoint(gridX.upper(),0,0))).y() << endl;
00164 
00165   cout << " GRID Y range: local " << gridY.lower() <<  " - " << gridY.upper()
00166        << " global: " << (frame().toGlobal(LocalPoint(0,gridY.lower(),0))).x() << " - " 
00167        << (frame().toGlobal(LocalPoint(0,gridY.upper(),0))).x() << endl;
00168 
00169   cout << " GRID Z range: local " << gridZ.lower() <<  " - " << gridZ.upper()
00170        << " global: " << (frame().toGlobal(LocalPoint(0,0,gridZ.lower()))).z() << " " 
00171        << (frame().toGlobal(LocalPoint(0,0,gridZ.upper()))).z() << endl;
00172 #endif
00173 
00174   if (increasingAlongX) {
00175     grid_ = GridType( gridX, gridY, gridZ, fieldValues);
00176   } else {
00177     // The reason why gridY and gridX have to be exchanged is because Grid3D::index(i,j,k)
00178     // assumes a specific order for the fieldValues, and we cannot rearrange this vector.
00179     // Given that we exchange grids, we will have to exchange the outpouts of mapping_rectangle()
00180     // and the inputs of mapping_.trapezoid() in the following...
00181     grid_ = GridType( gridY, gridX, gridZ, fieldValues);
00182   }
00183     
00184   
00185 #ifdef DEBUG_GRID
00186   dump();
00187 #endif
00188 }
00189 
00190 void TrapezoidalCartesianMFGrid::dump() const
00191 {
00192   
00193   cout << endl << "Dump of TrapezoidalCartesianMFGrid" << endl;
00194 //   cout << "Number of points from file   " 
00195 //        << n1 << " " << n2 << " " << n3 << endl;
00196   cout << "Number of points from Grid1D " 
00197        << grid_.grida().nodes() << " " << grid_.gridb().nodes() << " " << grid_.gridc().nodes() << endl;
00198 
00199 //   cout << "Reference Point from file   " 
00200 //        << xref << " " << yref << " " << zref << endl;
00201   cout << "Reference Point from Grid1D " 
00202        << grid_.grida().lower() << " " << grid_.gridb().lower() << " " << grid_.gridc().lower() << endl;
00203 
00204 //   cout << "Basic Distance from file   " 
00205 //        <<  stepx << " " << stepy << " " << stepz << endl;
00206   cout << "Basic Distance from Grid1D "
00207        << grid_.grida().step() << " " << grid_.gridb().step() << " " << grid_.gridc().step() << endl;
00208 
00209 
00210   cout << "Dumping " << grid_.data().size() << " field values " << endl;
00211   // grid_.dump();
00212   
00213 
00214   // Dump ALL grid points and values
00215   // CAVEAT: if convertToLocal = true in the ctor, points have been converted to LOCAL
00216   // coordinates. To match those from .table files they have to be converted back to global
00217 //   for (int j=0; j < grid_.gridb().nodes(); j++) {
00218 //     for (int i=0; i < grid_.grida().nodes(); i++) {
00219 //       for (int k=0; k < grid_.gridc().nodes(); k++) {
00220 //      cout << i << " " << j << " " << k << " "  
00221 //           << frame().toGlobal(LocalPoint(nodePosition(i,j,k))) << " "
00222 //           << nodeValue(i,j,k) << endl;
00223 //       }
00224 //     }
00225 //   }
00226   
00227 
00228 }
00229 
00230 MFGrid::LocalVector TrapezoidalCartesianMFGrid::uncheckedValueInTesla( const LocalPoint& p) const
00231 {
00232 
00233   double xrec, yrec;
00234   mapping_.rectangle( p.x(), p.y(), xrec, yrec);
00235   
00236 
00237 // cout << "TrapezoidalCartesianMFGrid::valueInTesla at local point " << p << endl;
00238 //   cout << p.x() << " " << p.y()  
00239 //        << " transformed to grid frame: " << xrec << " " << yrec << endl;
00240 
00241   LinearGridInterpolator3D interpol( grid_);
00242 
00243   if (!increasingAlongX) {
00244     std::swap(xrec,yrec);
00245     // B values are already converted to local coord!!! otherwise we should:
00246     // GridType::ValueType value = interpol.interpolate( xrec, yrec, p.z());
00247     // return LocalVector(value.y(),value.x(),-value.z());
00248   }
00249 
00250   return LocalVector(interpol.interpolate( xrec, yrec, p.z()));
00251 }
00252 
00253 void TrapezoidalCartesianMFGrid::toGridFrame( const LocalPoint& p, 
00254                                               double& a, double& b, double& c) const
00255 {
00256   if (increasingAlongX) {
00257     mapping_.rectangle( p.x(), p.y(), a, b);
00258   } else {
00259     mapping_.rectangle( p.x(), p.y(), b, a);
00260   }  
00261   
00262   c = p.z();
00263 }
00264  
00265 MFGrid::LocalPoint TrapezoidalCartesianMFGrid::fromGridFrame( double a, double b, double c) const
00266 {
00267   double xtrap, ytrap;
00268   if (increasingAlongX) {
00269     mapping_.trapezoid( a, b, xtrap, ytrap);
00270   } else {    
00271     mapping_.trapezoid( b, a, xtrap, ytrap);
00272   }
00273   return LocalPoint( xtrap, ytrap, c);
00274 }