src/BDS3DMagField.cc

00001 //Based on the Geant4 example examples/advanced/purging_magnet/src/PurgMagTabulatedField3D.cc
00002 #include <iostream>
00003 
00004 #include "BDSGlobalConstants.hh"
00005 #include "BDS3DMagField.hh"
00006 
00007 BDS3DMagField::BDS3DMagField( const char* filename, double zOffset ) 
00008   :fZoffset(zOffset),invertX(false),invertY(false),invertZ(false)
00009 {    
00010   fZoffset = -250*cm;
00011   zOffset = -250*cm;
00012   double lenUnit= m;
00013   double fieldUnit= tesla; 
00014   G4cout << "\n-----------------------------------------------------------"
00015          << "\n      Magnetic field"
00016          << "\n-----------------------------------------------------------";
00017     
00018   G4cout << "\n ---> " "Reading the field grid from " << filename << " ... " << G4endl; 
00019   std::ifstream file( filename ); // Open the file for reading.
00020   
00021   // Ignore first blank line
00022   char buffer[256];
00023   file.getline(buffer,256);
00024   
00025   // Read table dimensions 
00026   file >> nx >> ny >> nz; // Note dodgy order
00027 
00028   G4cout << "  [ Number of values x,y,z: " 
00029          << nx << " " << ny << " " << nz << " ] "
00030          << G4endl;
00031 
00032   // Set up storage space for table
00033   xField.resize( nx );
00034   yField.resize( nx );
00035   zField.resize( nx );
00036   int ix, iy, iz;
00037   for (ix=0; ix<nx; ix++) {
00038     xField[ix].resize(ny);
00039     yField[ix].resize(ny);
00040     zField[ix].resize(ny);
00041     for (iy=0; iy<ny; iy++) {
00042       xField[ix][iy].resize(nz);
00043       yField[ix][iy].resize(nz);
00044       zField[ix][iy].resize(nz);
00045     }
00046   }
00047   
00048   // Ignore other header information    
00049   // The first line whose second character is '0' is considered to
00050   // be the last line of the header.
00051   do {
00052     file.getline(buffer,256);
00053   } while ( buffer[1]!='0');
00054   
00055   // Read in the data
00056   double xval,yval,zval,bx,by,bz;
00057   //  double permeability; // Not used in this example.
00058   for (ix=0; ix<nx; ix++) {
00059     for (iy=0; iy<ny; iy++) {
00060       for (iz=0; iz<nz; iz++) {
00061         file >> xval >> yval >> zval >> bx >> by >> bz;
00062         if ( ix==0 && iy==0 && iz==0 ) {
00063           minx = xval * lenUnit;
00064           miny = yval * lenUnit;
00065           minz = zval * lenUnit;
00066         }
00067         xField[ix][iy][iz] = bx * fieldUnit;
00068         yField[ix][iy][iz] = by * fieldUnit;
00069         zField[ix][iy][iz] = bz * fieldUnit;
00070       }
00071     }
00072   }
00073   file.close();
00074 
00075   maxx = xval * lenUnit;
00076   maxy = yval * lenUnit;
00077   maxz = zval * lenUnit;
00078 
00079   G4cout << "\n ---> ... done reading " << G4endl;
00080 
00081   // G4cout << " Read values of field from file " << filename << G4endl; 
00082   G4cout << " ---> assumed the order:  x, y, z, Bx, By, Bz "
00083          << "\n ---> Min values x,y,z: " 
00084          << minx/cm << " " << miny/cm << " " << minz/cm << " cm "
00085          << "\n ---> Max values x,y,z: " 
00086          << maxx/cm << " " << maxy/cm << " " << maxz/cm << " cm "
00087          << "\n ---> The field will be offset by " << zOffset/cm << " cm " << G4endl;
00088 
00089   // Should really check that the limits are not the wrong way around.
00090   if (maxx < minx) {std::swap(maxx,minx); invertX = true;} 
00091   if (maxy < miny) {std::swap(maxy,miny); invertY = true;} 
00092   if (maxz < minz) {std::swap(maxz,minz); invertZ = true;} 
00093   G4cout << "\nAfter reordering if neccesary"  
00094          << "\n ---> Min values x,y,z: " 
00095          << minx/cm << " " << miny/cm << " " << minz/cm << " cm "
00096          << " \n ---> Max values x,y,z: " 
00097          << maxx/cm << " " << maxy/cm << " " << maxz/cm << " cm ";
00098 
00099   dx = maxx - minx;
00100   dy = maxy - miny;
00101   dz = maxz - minz;
00102   G4cout << "\n ---> Dif values x,y,z (range): " 
00103          << dx/cm << " " << dy/cm << " " << dz/cm << " cm in z "
00104          << "\n-----------------------------------------------------------" << G4endl;
00105 }
00106 
00107 void BDS3DMagField::GetFieldValue(const double point[4],
00108                                       double *Bfield ) const
00109 {
00110 
00111   double x = point[0];
00112   double y = point[1];
00113   double z = point[2] + fZoffset;
00114 
00115   double signy=1;
00116   double signz=1;
00117 
00118   //Mirror in x=0 plane and z=0 plane
00119   if( x < 0 ){
00120 #ifdef DEBUG
00121     G4cout << "x = " << x << ". Mirroring in x=0 plane." << G4endl;
00122 #endif
00123     x *= -1;
00124     signy = -1;
00125     signz = -1;
00126   }
00127 
00128   if( z <0 ){
00129 #ifdef DEBUG
00130     G4cout << "z = " << z << ". Mirroring in z=0 plane." << G4endl;
00131 #endif
00132     z *= -1;
00133     signz = -1;
00134   }
00135   
00136   // Check that the point is within the defined region 
00137   if ( x>=minx && x<=maxx &&
00138        y>=miny && y<=maxy && 
00139        z>=minz && z<=maxz ) {
00140     
00141     // Position of given point within region, normalized to the range
00142     // [0,1]
00143     double xfraction = (x - minx) / dx;
00144     double yfraction = (y - miny) / dy; 
00145     double zfraction = (z - minz) / dz;
00146 
00147     if (invertX) { xfraction = 1 - xfraction;}
00148     if (invertY) { yfraction = 1 - yfraction;}
00149     if (invertZ) { zfraction = 1 - zfraction;}
00150 
00151     // Need addresses of these to pass to modf below.
00152     // modf uses its second argument as an OUTPUT argument.
00153     double xdindex, ydindex, zdindex;
00154     
00155     // Position of the point within the cuboid defined by the
00156     // nearest surrounding tabulated points
00157     double xlocal = ( std::modf(xfraction*(nx-1), &xdindex));
00158     double ylocal = ( std::modf(yfraction*(ny-1), &ydindex));
00159     double zlocal = ( std::modf(zfraction*(nz-1), &zdindex));
00160     
00161     // The indices of the nearest tabulated point whose coordinates
00162     // are all less than those of the given point
00163     int xindex = static_cast<int>(xdindex);
00164     int yindex = static_cast<int>(ydindex);
00165     int zindex = static_cast<int>(zdindex);
00166     
00167 
00168 #ifdef DEBUG_INTERPOLATING_FIELD
00169     G4cout << "Local x,y,z: " << xlocal << " " << ylocal << " " << zlocal << G4endl;
00170     G4cout << "Index x,y,z: " << xindex << " " << yindex << " " << zindex << G4endl;
00171     double valx0z0, mulx0z0, valx1z0, mulx1z0;
00172     double valx0z1, mulx0z1, valx1z1, mulx1z1;
00173     //    valx0z0= table[xindex  ][0][zindex];  mulx0z0=  (1-xlocal) * (1-zlocal);
00174     //    valx1z0= table[xindex+1][0][zindex];  mulx1z0=   xlocal    * (1-zlocal);
00175     //    valx0z1= table[xindex  ][0][zindex+1]; mulx0z1= (1-xlocal) * zlocal;
00176     //    valx1z1= table[xindex+1][0][zindex+1]; mulx1z1=  xlocal    * zlocal;
00177 #endif
00178 
00179         // Full 3-dimensional version
00180     Bfield[0] =
00181       xField[xindex  ][yindex  ][zindex  ] * (1-xlocal) * (1-ylocal) * (1-zlocal) +
00182       xField[xindex  ][yindex  ][zindex+1] * (1-xlocal) * (1-ylocal) *    zlocal  +
00183       xField[xindex  ][yindex+1][zindex  ] * (1-xlocal) *    ylocal  * (1-zlocal) +
00184       xField[xindex  ][yindex+1][zindex+1] * (1-xlocal) *    ylocal  *    zlocal  +
00185       xField[xindex+1][yindex  ][zindex  ] *    xlocal  * (1-ylocal) * (1-zlocal) +
00186       xField[xindex+1][yindex  ][zindex+1] *    xlocal  * (1-ylocal) *    zlocal  +
00187       xField[xindex+1][yindex+1][zindex  ] *    xlocal  *    ylocal  * (1-zlocal) +
00188       xField[xindex+1][yindex+1][zindex+1] *    xlocal  *    ylocal  *    zlocal ;
00189     Bfield[1] = signy *(
00190       yField[xindex  ][yindex  ][zindex  ] * (1-xlocal) * (1-ylocal) * (1-zlocal) +
00191       yField[xindex  ][yindex  ][zindex+1] * (1-xlocal) * (1-ylocal) *    zlocal  +
00192       yField[xindex  ][yindex+1][zindex  ] * (1-xlocal) *    ylocal  * (1-zlocal) +
00193       yField[xindex  ][yindex+1][zindex+1] * (1-xlocal) *    ylocal  *    zlocal  +
00194       yField[xindex+1][yindex  ][zindex  ] *    xlocal  * (1-ylocal) * (1-zlocal) +
00195       yField[xindex+1][yindex  ][zindex+1] *    xlocal  * (1-ylocal) *    zlocal  +
00196       yField[xindex+1][yindex+1][zindex  ] *    xlocal  *    ylocal  * (1-zlocal) +
00197       yField[xindex+1][yindex+1][zindex+1] *    xlocal  *    ylocal  *    zlocal );
00198     Bfield[2] = signz *(
00199       zField[xindex  ][yindex  ][zindex  ] * (1-xlocal) * (1-ylocal) * (1-zlocal) +
00200       zField[xindex  ][yindex  ][zindex+1] * (1-xlocal) * (1-ylocal) *    zlocal  +
00201       zField[xindex  ][yindex+1][zindex  ] * (1-xlocal) *    ylocal  * (1-zlocal) +
00202       zField[xindex  ][yindex+1][zindex+1] * (1-xlocal) *    ylocal  *    zlocal  +
00203       zField[xindex+1][yindex  ][zindex  ] *    xlocal  * (1-ylocal) * (1-zlocal) +
00204       zField[xindex+1][yindex  ][zindex+1] *    xlocal  * (1-ylocal) *    zlocal  +
00205       zField[xindex+1][yindex+1][zindex  ] *    xlocal  *    ylocal  * (1-zlocal) +
00206       zField[xindex+1][yindex+1][zindex+1] *    xlocal  *    ylocal  *    zlocal );
00207 
00208   } else {
00209     Bfield[0] = 0.0;
00210     Bfield[1] = 0.0;
00211     Bfield[2] = 0.0;
00212   }
00213 }
00214 

Generated on 27 Aug 2013 for BDSIM by  doxygen 1.4.7