BLCoil Class Reference

#include <BLCoil.hh>

Inheritance diagram for BLCoil:

BLCMDcoil

List of all members.


Detailed Description

BLCoil creates and implements a coil (part of a solenoid).

A BLCoil consists only of the parameters describing the coil geometry and a field map for unit current density. It is not a BLElement, and cannot be placed geometrically -- see BLSolenoid for that.

Cylindrical symmetry around z is assumed. The field is approximated by computing the field from nSheets infinitesimally-thin current sheets interpolating from innerRadius to OuterRadius, each length long. The solution to Maxwell's Equations for each sheet is used.

The field has been verified to be correct within 0.2% for both a long solenoid and for a pair of Helmholtz coils.

Effect of nSheets on accuracy: consider the coil innerRadius=330.0*mm, outerRadius=505.0*mm, length=167.0*mm. Compute the maximum error for 1000 random points, excluding the region within 2 cm of the coils; use 99 sheets as the "correct" value. In the region 0<=r<2*outerRadius, 0<z<10*outerRadius, for 0.1% accuracy one needs 11 sheets, and for 1% one needs 4 sheets. In the region 0<=r<innerRadius/2, same z, for 0.1% accuracy one needs 5 sheets, and for 1% one needs 2 sheets. Note that inside the coils this approximation of using thin sheets is not very good; but interpolating on a grid and coordinating sheet positions with the grid is probably about as good as one can do -- at least the values will be smooth (which is not true for the bare computation -- there's a singularity at every sheet, and Bz jumps from +infinity to -infinity across the sheet).

Note that Bz does not decrease to 0.1% of its central value until z>10*(innerRadius+outerRadius)/2; it decreases to 1% at ~5 times that average radius.

BLCoil can also read a mapFile defining the field (rather than doing the above computation). For instance, it could be from opera-2d. The mapFile gives tables of Bz and Br on a grid in the z-r plane. mapFile format: lines beginning with # are comments, and are ignored. The first line contains the parameters in name=value form: z0 initial value of z (mm) dz grid interval along z (mm) nz number of grid points along z dr grid interval along r (mm) nr number of grid points along r reflectZ set nonzero to reflect in the z=0 plane (inverting Br) current the current for this field (A/mm^2) All parameters are required. If reflectZ is nonzero then z0 must be 0.0 (only z>=0 is contained in the file). The point with local coordinates (z=0,r=0) is what gets placed.

Then follow the two maps in any order. Each map begins with a line giving its name (Bz or Br) in column 1, followed by nz lines each containing nr floats (Tesla). The first value in each line is for r=0. Values are separated by one or more spaces (the first value on each line may but need not be preceeded by spaces). The main reason to use a mapFile is to accurately include the effects of iron. That implies that the map may not be accurate for values of current other than that for which the map was generated.

See BLCMDfieldmap for a more general EM field read from a map-file.

BLCoil was separated from BLSolenoid so multiple solenoids with the same geometry (coil) could share a single (large) field map for the coil -- the B field is scaled by current/currentOfMap, where currentOfMap is 1.0 for the computed field, and is the current parameter from a mapFile.

This class does not use BLFieldMap becuase it predates it, and because the map must include the parameters so construct() will know whether or not the map corresponds to the current values. You can, of course, build a solenoid out of a BLTubs and a BLFieldMap.

Public Member Functions

 BLCoil ()
 Default constructor.
 BLCoil (G4String _name, G4double _innerRadius, G4double _outerRadius, G4double _length, G4int _nSheets=0, G4double _tolerance=0.0, G4double _maxR=0.0, G4double _maxZ=0.0, G4double _dR=0.0, G4double _dZ=0.0, G4int _nR=0, G4int _nZ=0, G4String _filename="")
 Complex Constructor. All arguments that default to 0 are related to generating the field map; those that are 0 will be determined by tolerance. To construct the map the minimum info is tolerance and maxR; if either of them is 0, no map will be generated or used. NOTE: without a map, field values inside the coils will fluctuate wildly, because points on the sheets are singular; map construction is designed to minimize this. Without a map, nSheets must be given. tolerance is a fraction of the best value at r=0,z=0; values smaller than about 0.001 are unrealistic (and expensive!).
virtual ~BLCoil ()
 Destructor.
 BLCoil (const BLCoil &r)
 Copy constructor.
void printCoil ()
 printCoil() will print a description
void addField (const G4double point[4], G4double field[6], G4double currentAmpPerMm2) const
 addField() adds the field value for the given point[] into field[]. Note that point[] is relative to the center of the coil. Units for current are Amp/mm^2.
void generateFieldMap ()
 generateFieldMap() will generate the field map (for execution speedup). If just maxR and tolerance were given, all other map parameters will be automatically determined so that the estimated error is less than the specified tolerance. The field map is cached in a disk file which is automatically recreated if anything changes (may take several minutes).
void readMapFile ()
 readMapFile() will read the mapFile.
void displayMapValues (G4double r, G4double z)
 displayMapValues() will display the 4 map values around a point.

Static Public Member Functions

static BLCoilfind (G4String name)
 find() returns a pointer to the named BLCoil.

Private Member Functions

void getUnitField (G4double r, G4double z, G4double &Br, G4double &Bz)
 getUnitField() will return Br and Bz for unit current.
void determineMaxR ()
 determineMaxR() will determine maxR based on tolerance. Uses nSheets=99 to determine center field, and walks out far enough so (Bz/Bz0)<0.5*tolerance.
void determineMaxZ ()
 determineMaxZ() will determine maxZ based on tolerance. Uses nSheets=99 to determine on-axis field, and walks out far enough so (Bz/Bz0)<0.5*tolerance.
void determineNsheets ()
 determineNsheets() will determine nSheets, given maxZ and tolerance. Increases nSheets until maxError < tolerance/4 (the other 3/4 of tolerance is for mapping errors). Checks just a handful of points selected to be representative.
G4double estimateMapError ()
 estimateMapError() will estimate the maximum error in mapping, given maxZ, nSheets, dR, dZ, nR, nZ, and an allocated but uninitialized fieldMap. It generates 1000 random points and returns the maximum error; quits early if tolerance is exceeded. Error is (currentMap - best)/best(r=0,z=0), where best is computed with no map and nSheets=99. For each point it generates the 4 surrounding values of fieldMap (this is faster than generating the entire map first). Returns the maximum error of either Bz or Br, normalized to Bz(r=0,z=0,nSheets=99).
G4double computeError (G4double r, G4double z, BLCoil &best, G4bool makeMap)
 computeError() computes the error for a single point. Error is (currentMap - best)/best(r=0,z=0), where best should be an identical BLCoil with no map and nSheets=99. If makeMap is true, it generates the 4 surrounding values of the fieldMap.
void getSheetField (G4double r, G4double z, G4double &Br, G4double &Bz, G4double sheetR, G4double sheetLen, G4double currentAmpPerMm) const
 getSheetField() returns the B field from an infinitesimally-thin sheet of current. Arguments: r and z are the cylindrical coordinates of the point in question relative to center of the coil (axis along z), mm. Br and Bz return the computed B field at that point (geant4 units) sheetR is the radius of the current sheet (mm) sheetLen is the length of the current sheet (mm) currentAmpPerMm is the current of the sheet (Amp per linear mm)

Private Attributes

G4String name
G4double innerRadius
G4double outerRadius
G4double length
G4int nSheets
G4String material
G4double tolerance
G4double maxR
G4double minZ
G4double maxZ
G4double dR
G4double dZ
G4int nR
G4int nZ
G4String filename
G4String mapFile
G4int exactComputation
float * mapBr
float * mapBz
G4double sheetR0
G4double sheetDR
G4double norm
G4bool goodMap
G4bool reflectZ
G4double currentOfMap

Static Private Attributes

static std::map< G4String,
BLCoil * > 
mapCoil

Friends

class BLCMDcoil
class BLCMDsolenoid
class SolenoidField


Constructor & Destructor Documentation

BLCoil::BLCoil (  ) 

Default constructor.

References currentOfMap, dR, dZ, exactComputation, filename, goodMap, innerRadius, length, mapBr, mapBz, mapFile, material, maxR, maxZ, minZ, name, norm, nR, nSheets, nZ, outerRadius, reflectZ, sheetDR, sheetR0, and tolerance.

00034 {
00035         // provide initial values for fields
00036         name = "";
00037         innerRadius = 0.0;
00038         outerRadius = 0.0;
00039         length = 0.0;
00040         nSheets = 0;
00041         material = "Cu";
00042         tolerance = 0.002;
00043         maxR = 0.0;
00044         minZ = 0.0;
00045         maxZ = 0.0;
00046         dR = 0.0;
00047         dZ = 0.0;
00048         nR = 0;
00049         nZ = 0;
00050         filename = "";
00051         exactComputation = 0;
00052         mapFile = "";
00053         mapBr = 0;
00054         mapBz = 0;
00055         sheetR0 = 0.0;
00056         sheetDR = 0.0;
00057         norm = 0.0;
00058         goodMap = false;
00059         reflectZ = true;
00060         currentOfMap = 1.0;
00061 }

BLCoil::BLCoil ( G4String  _name,
G4double  _innerRadius,
G4double  _outerRadius,
G4double  _length,
G4int  _nSheets = 0,
G4double  _tolerance = 0.0,
G4double  _maxR = 0.0,
G4double  _maxZ = 0.0,
G4double  _dR = 0.0,
G4double  _dZ = 0.0,
G4int  _nR = 0,
G4int  _nZ = 0,
G4String  _filename = "" 
) [inline]

Complex Constructor. All arguments that default to 0 are related to generating the field map; those that are 0 will be determined by tolerance. To construct the map the minimum info is tolerance and maxR; if either of them is 0, no map will be generated or used. NOTE: without a map, field values inside the coils will fluctuate wildly, because points on the sheets are singular; map construction is designed to minimize this. Without a map, nSheets must be given. tolerance is a fraction of the best value at r=0,z=0; values smaller than about 0.001 are unrealistic (and expensive!).

References dR, dZ, exactComputation, filename, goodMap, innerRadius, length, mapBr, mapBz, maxR, maxZ, name, norm, nR, nSheets, nZ, outerRadius, sheetDR, sheetR0, and tolerance.

00153                                        {
00154                         name=_name; innerRadius=_innerRadius;
00155                         outerRadius=_outerRadius; length=_length;
00156                         nSheets=_nSheets; tolerance=_tolerance; maxR=_maxR;
00157                         maxZ=_maxZ; dR=_dR; dZ=_dZ; nR=_nR; nZ=_nZ; 
00158                         filename = _filename;
00159                         exactComputation = 0;
00160                         mapBr=0; mapBz=0; sheetR0=0.0; sheetDR=0.0; norm=0.0; 
00161                         goodMap=false; 
00162                         if(nSheets > 0) { 
00163                                 sheetDR=(outerRadius-innerRadius)/nSheets;
00164                                 sheetR0=innerRadius + sheetDR/2.0;
00165                         }
00166                         if(filename == "") filename = name + ".dat";
00167                 }

BLCoil::~BLCoil (  )  [virtual]

Destructor.

References mapBr, and mapBz.

00064 {
00065         if(mapBr) delete[] mapBr;
00066         mapBr = 0;
00067         if(mapBz) delete[] mapBz;
00068         mapBz = 0;
00069 }

BLCoil::BLCoil ( const BLCoil r  ) 

Copy constructor.

References currentOfMap, dR, dZ, exactComputation, filename, goodMap, innerRadius, length, mapBr, mapBz, mapFile, material, maxR, maxZ, minZ, name, norm, nR, nSheets, nZ, outerRadius, reflectZ, sheetDR, sheetR0, and tolerance.

00072 {
00073         name = "";
00074         innerRadius = r.innerRadius;
00075         outerRadius = r.outerRadius;
00076         length = r.length;
00077         nSheets = r.nSheets;
00078         material = r.material;
00079         tolerance = r.tolerance;
00080         maxR = r.maxR;
00081         minZ = r.minZ;
00082         maxZ = r.maxZ;
00083         dR = r.dR;
00084         dZ = r.dZ;
00085         nR = r.nR;
00086         nZ = r.nZ;
00087         filename = r.filename;
00088         exactComputation = r.exactComputation;
00089         mapFile = r.mapFile;
00090         mapBr = 0;
00091         mapBz = 0;
00092         sheetR0 = r.sheetR0;
00093         sheetDR = r.sheetDR;
00094         norm = 0.0;
00095         goodMap = false;
00096         reflectZ = r.reflectZ;
00097         currentOfMap = r.currentOfMap;
00098 }


Member Function Documentation

void BLCoil::printCoil (  ) 

printCoil() will print a description

References dR, dZ, filename, innerRadius, length, mapFile, material, maxR, maxZ, name, nSheets, outerRadius, and tolerance.

Referenced by BLCMDcoil::command().

00101 {
00102         printf("coil    %-7s ",name.c_str());
00103         printf("innerRadius=%.1f ",innerRadius);
00104         printf("outerRadius=%.1f ",outerRadius);
00105         printf("length=%.1f ",length);
00106         printf("material=%s ",material.c_str());
00107         printf("\n\t\t");
00108         if(mapFile == "") {
00109                 printf("tolerance=%.3f ",tolerance);
00110                 printf("nSheets=%d ",nSheets);
00111                 printf("\n\t\t");
00112                 printf("maxR=%.1f ",maxR);
00113                 printf("maxZ=%.1f ",maxZ);
00114                 printf("dR=%.1f ",dR);
00115                 printf("dZ=%.1f ",dZ);
00116                 printf("filename=%s ",filename.c_str());
00117                 printf("\n");
00118         } else {
00119                 printf("mapFile=%s\n",mapFile.c_str());
00120         }
00121 }

BLCoil * BLCoil::find ( G4String  name  )  [static]

find() returns a pointer to the named BLCoil.

References mapCoil.

Referenced by BLCMDsolenoid::command().

00124 {
00125         if(mapCoil.count(name) > 0)
00126                 return mapCoil[name];
00127         return 0;
00128 }

void BLCoil::addField ( const G4double  point[4],
G4double  field[6],
G4double  currentAmpPerMm2 
) const

addField() adds the field value for the given point[] into field[]. Note that point[] is relative to the center of the coil. Units for current are Amp/mm^2.

References BLAssert, currentOfMap, dR, dZ, exactComputation, getSheetField(), goodMap, innerRadius, length, mapBr, mapBz, maxR, maxZ, minZ, name, nR, nSheets, nZ, outerRadius, reflectZ, sheetDR, and sheetR0.

Referenced by SolenoidField::addFieldValue(), and getUnitField().

00132 {
00133         G4double z = point[2];
00134         G4double r = sqrt(point[0]*point[0] + point[1]*point[1]);
00135 
00136         if(goodMap && exactComputation == 0) {
00137                 BLAssert(mapBr != 0 && mapBz != 0 && dR > 0.0 && dZ > 0.0);
00138                 BLAssert(nR > 0 && nZ > 0);
00139                 if(z < minZ+0.002*mm || z > maxZ-0.002*mm || r > maxR-0.002*mm)
00140                         return;
00141                 G4double sign = 1.0;
00142                 if(reflectZ) {
00143                         // map covers only z >= 0
00144                         if(z < 0.0) {
00145                                 sign = -sign;
00146                                 z = -z;
00147                         }
00148                 } else {
00149                         z -= minZ;
00150                 }
00151                 // 2-d linear average of the 4 surrounding points
00152                 int i = (int)(r/dR);
00153                 int j = (int)(z/dZ);
00154 if(i >= 0 && i < nR-1 && j >= 0 && j < nZ-1) {
00155   ;
00156 } else {
00157   printf("\ni=%d j=%d nR=%d nZ=%d r=%.3f z=%.3f dR=%.3f dZ=%.3f\n",i,j,nR,nZ,r,z,dR,dZ);
00158   printf("z=%.6f maxZ=%.6f r=%.6f maxR=%.5f\n",z,maxZ,r,maxR);
00159   fflush(stdout);
00160 }
00161                 BLAssert(i >= 0 && i < nR-1 && j >= 0 && j < nZ-1);
00162                 float fr = 1.0 - (r - i*dR) / dR;
00163                 BLAssert(fr >= 0.0 && fr <= 1.0);
00164                 float fz = 1.0 - (z - j*dZ) / dZ;
00165                 BLAssert(fz >= 0.0 && fz <= 1.0);
00166         
00167                 G4double Bz = mapBz[j*nR+i]*fr*fz +
00168                         mapBz[j*nR+i+1]*(1.0-fr)*fz +
00169                         mapBz[(j+1)*nR+i]*fr*(1.0-fz) +
00170                         mapBz[(j+1)*nR+i+1]*(1.0-fr)*(1.0-fz);
00171                 G4double Br = mapBr[j*nR+i]*fr*fz +
00172                         mapBr[j*nR+i+1]*(1.0-fr)*fz +
00173                         mapBr[(j+1)*nR+i]*fr*(1.0-fz) +
00174                         mapBr[(j+1)*nR+i+1]*(1.0-fr)*(1.0-fz);
00175                 G4double phi = atan2(point[1], point[0]);
00176                 currentAmpPerMm2 /= currentOfMap;
00177                 field[0] += sign * currentAmpPerMm2 * Br * cos(phi);
00178                 field[1] += sign * currentAmpPerMm2 * Br * sin(phi);
00179                 field[2] += currentAmpPerMm2 * Bz;
00180                 return;
00181         }
00182 
00183         // Computation for no map
00184 if(nSheets > 0 && sheetDR > 0.0 && sheetR0 > 0.0); else printf("%s: nSheets=%d sheetR0=%.3f sheetDR=%.3f innerRadius=%.3f outerRadius=%.3f length=%.3f\n",name.c_str(),nSheets,sheetR0,sheetDR,innerRadius,outerRadius,length);
00185         BLAssert(nSheets > 0 && sheetDR > 0.0 && sheetR0 > 0.0);
00186         G4double Br=0.0, Bz=0.0;
00187         G4double rSheet = sheetR0;
00188         G4double currentAmpPerMm = currentAmpPerMm2 * sheetDR;
00189         for(int i=0; i<nSheets; ++i) {
00190                 G4double br, bz;
00191                 // avoid singularity when r==rSheet
00192                 if(fabs(r-rSheet) < sheetDR/8.0) {
00193                     getSheetField(r+sheetDR/4.0,z,br,bz,rSheet,length,
00194                                                         currentAmpPerMm);
00195                     G4double br1, bz1;
00196                     getSheetField(r-sheetDR/4.0,z,br1,bz1,rSheet,length,
00197                                                         currentAmpPerMm);
00198                     br = (br+br1)/2.0;
00199                     bz = (bz+bz1)/2.0;
00200                 } else {
00201                     getSheetField(r,z,br,bz,rSheet,length,currentAmpPerMm);
00202                 }
00203                 Br += br;
00204                 Bz += bz;
00205                 rSheet += sheetDR;
00206         }
00207         G4double phi = atan2(point[1], point[0]);
00208         field[0] += Br * cos(phi);
00209         field[1] += Br * sin(phi);
00210         field[2] += Bz;
00211 }

void BLCoil::generateFieldMap (  ) 

generateFieldMap() will generate the field map (for execution speedup). If just maxR and tolerance were given, all other map parameters will be automatically determined so that the estimated error is less than the specified tolerance. The field map is cached in a disk file which is automatically recreated if anything changes (may take several minutes).

References BLAssert, currentOfMap, determineMaxR(), determineMaxZ(), determineNsheets(), dR, dZ, estimateMapError(), exactComputation, filename, getUnitField(), goodMap, innerRadius, length, mapBr, mapBz, mapFile, maxR, maxZ, minZ, name, norm, nR, nSheets, nZ, outerRadius, readMapFile(), reflectZ, sheetDR, sheetR0, BLTime::time(), and tolerance.

Referenced by BLCMDcoil::command().

00214 {
00215         if(exactComputation != 0) {
00216                 minZ = -DBL_MAX;
00217                 maxZ = DBL_MAX;
00218                 maxR = DBL_MAX;
00219                 if(nSheets <= 0) nSheets = 1;
00220                 sheetDR = (outerRadius-innerRadius) / nSheets;
00221                 sheetR0 = innerRadius + sheetDR/2.0;
00222                 return;
00223         }
00224 
00225         if(mapFile != "") {
00226                 readMapFile();
00227                 return;
00228         }
00229 
00230         struct FileHeader {
00231                 long magic, nR, nZ, nSheets;
00232                 double innerRadius, outerRadius, length, dR, dZ, error;
00233                 // followed by nR*nZ  float-s of mapBr
00234                 // followed by nR*nZ  float-s of mapBz
00235         };
00236         // Had serious problems with files written on a different OS that
00237         // passed the check but generated gross tracking errors and/or
00238         // exceptions in malloc/free. Probably different compilers padding
00239         // FileHeader differently.
00240 #ifdef __linux
00241         const int MAGIC = 0x544A5232;   // 'TJR2'
00242 #endif
00243 #ifdef WIN32
00244         const int MAGIC = 0x544A5235;   // 'TJR5'
00245 #endif
00246 #ifdef __APPLE__
00247         const int MAGIC = 0x544A5234;   // 'TJR4'
00248 #endif
00249 #ifdef __CYGWIN__
00250         const int MAGIC = 0x544A5235;   // 'TJR5'
00251 #endif
00252 
00253         printf("coilmap %-7s tolerance=%.5f [fraction of "
00254                                 "Bz(r=0,z=0)]\n",name.c_str(),tolerance);
00255         fflush(stdout);
00256         goodMap = false;
00257 
00258         // read FileHeader from filename (if it exists), and check for 
00259         // consistency with this coil
00260 #ifdef WIN32
00261         FILE *in = fopen(filename.c_str(),"rb");
00262 #else
00263         FILE *in = fopen(filename.c_str(),"r");
00264 #endif
00265         FileHeader fh;
00266         if(in) {
00267                 if(fread(&fh,sizeof(fh),1,in) != 1) {
00268                         printf("BLCoil::generateFieldMap Cannot read header\n");
00269                         if(in) fclose(in);
00270                         in = 0;
00271                 }
00272                 if(fh.magic != MAGIC) {
00273                         printf("BLCoil::generateFieldMap wrong magic\n");
00274                         if(in) fclose(in);
00275                         in = 0;
00276                 }
00277                 if(fh.error > tolerance) {
00278                         printf("BLCoil::generateFieldMap error > tolerance\n");
00279                         if(in) fclose(in);
00280                         in = 0;
00281                 }
00282                 if(fabs(fh.innerRadius-innerRadius) > 0.001*mm) {
00283                         printf("BLCoil::generateFieldMap wrong innerRadius\n");
00284                         if(in) fclose(in);
00285                         in = 0;
00286                 }
00287                 if(fabs(fh.outerRadius-outerRadius) > 0.001*mm) {
00288                         printf("BLCoil::generateFieldMap wrong outerRadius\n");
00289                         if(in) fclose(in);
00290                         in = 0;
00291                 }
00292                 if(fabs(fh.length-length) > 0.001*mm) {
00293                         printf("BLCoil::generateFieldMap wrong length\n");
00294                         if(in) fclose(in);
00295                         in = 0;
00296                 }
00297                 if((dR > 0.001*mm && fabs(fh.dR-dR) > 0.001*mm)) {
00298                         printf("BLCoil::generateFieldMap wrong dR\n");
00299                         if(in) fclose(in);
00300                         in = 0;
00301                 }
00302                 if((dZ > 0.001*mm && fabs(fh.dZ-dZ) > 0.001*mm)) {
00303                         printf("BLCoil::generateFieldMap wrong dZ\n");
00304                         if(in) fclose(in);
00305                         in = 0;
00306                 }
00307                 if((fh.nR-1)*fh.dR < maxR || (fh.nZ-1)*fh.dZ < maxZ) {
00308                         printf("BLCoil::generateFieldMap wrong maxR or maxZ\n");
00309                         if(in) fclose(in);
00310                         in = 0;
00311                 }
00312         }
00313         // setup data from file and read the maps from file
00314         if(in) {
00315                 G4double orgMaxZ = maxZ;
00316                 G4double orgMaxR = maxR;
00317                 G4int orgNsheets = nSheets;
00318                 nR = fh.nR;
00319                 nZ = fh.nZ;
00320                 dR = fh.dR;
00321                 dZ = fh.dZ;
00322                 nSheets = fh.nSheets;
00323                 sheetDR=(outerRadius-innerRadius)/nSheets;
00324                 sheetR0=innerRadius + sheetDR/2.0;
00325                 norm = 0.0;
00326                 maxR = (nR-1)*dR;
00327                 maxZ = (nZ-1)*dZ;
00328                 minZ = -maxZ;
00329                 if(mapBr) delete[] mapBr;
00330                 if(mapBz) delete[] mapBz;
00331                 mapBr = new float[nZ*nR];
00332                 mapBz = new float[nZ*nR];
00333                 if(!mapBr || !mapBz) {
00334                         G4Exception("coil","Out of memory",FatalException,"");
00335                 }
00336                 if(fread(mapBr,sizeof(float),nR*nZ,in) != (size_t)nR*nZ ||
00337                    fread(mapBz,sizeof(float),nR*nZ,in) != (size_t)nR*nZ) {
00338                         fclose(in);
00339                         in = 0;
00340                         printf("BLCoil::generateFieldMap cannot read data\n");
00341                         // restore invalid data that came from file
00342                         maxZ = orgMaxZ;
00343                         minZ = -maxZ;
00344                         reflectZ = true;
00345                         maxR = orgMaxR;
00346                         nSheets = orgNsheets;
00347                 }
00348         }
00349         // if file is correct, use it.
00350         if(in) {
00351                 fclose(in);
00352                 in = 0;
00353                 goodMap = true;
00354                 printf("coilmap %-7s read file '%s'  "
00355                     "dR=%.1f dZ=%.1f\n",name.c_str(),filename.c_str(),dR,dZ);
00356                 minZ = -maxZ;
00357                 reflectZ = true;
00358                 currentOfMap = 1.0;
00359                 return;
00360         }
00361 
00362         // file is not correct - generate map
00363 
00364         if(maxR <= 0.0)
00365                 determineMaxR();
00366         if(maxZ <= 0.0)
00367                 determineMaxZ();
00368         if(nSheets <= 0) {
00369                 determineNsheets();
00370         } else {
00371                 sheetDR = (outerRadius-innerRadius) / nSheets;
00372                 sheetR0 = innerRadius + sheetDR/2.0;
00373         }
00374 
00375         // initial estimate of dR,dZ,nR,nZ
00376         if(dR <= 0.0)
00377                 dR = maxR/10;
00378         nR = (int)floor(maxR/dR) + 2;
00379         //@@ for now, assume dZ = dR....
00380         if(dZ <= 0.0)
00381                 dZ = dR;
00382         nZ = (int)floor(maxZ/dZ) + 2;
00383 
00384         // loop until we achieve the required tolerance. Limit to 8 doublings.
00385         const int MAX_ITER=8;
00386         int iter;
00387         G4double err = 1.0;
00388         for(iter=0; iter<MAX_ITER; ++iter) {
00389                 // for simplicity, discard all previous computations
00390                 if(mapBr) delete[] mapBr;
00391                 if(mapBz) delete[] mapBz;
00392                 mapBr = new float[nZ*nR];
00393                 mapBz = new float[nZ*nR];
00394                 if(!mapBr || !mapBz) {
00395                         G4Exception("coil","Out of memory",FatalException,"");
00396                 }
00397                 err = estimateMapError();
00398                 if(err < tolerance)
00399                         break;
00400                 dR /= 2.0;
00401                 dZ /= 2.0;
00402                 nR = (int)floor(maxR/dR) + 2;
00403                 nZ = (int)floor(maxZ/dZ) + 2;
00404         }
00405         if(iter >= MAX_ITER) {
00406                 G4Exception("coilmap","Failed to achieve required accuracy",
00407                                                         FatalException, "");
00408         }
00409         printf("coilmap %-7s nR=%d nZ=%d dR=%.1f dZ=%.1f "
00410                         "error=%.6f\n",name.c_str(),nR,nZ,dR,dZ,err);
00411 
00412         // fill the maps
00413         //@@ for simplicity, ignore all previous computations
00414         goodMap = false;
00415         time_t start = BLTime::time();
00416         for(int i=0; i<nR; ++i) {
00417                 G4double r = i * dR;
00418                 for(int j=0; j<nZ; ++j) {
00419                         G4double z = j * dZ;
00420                         int k = j * nR + i;
00421                         BLAssert( k >= 0 && k < nZ*nR);
00422                         G4double Br,Bz;
00423                         getUnitField(r,z,Br,Bz);
00424                         mapBr[k] = Br;
00425                         mapBz[k] = Bz;
00426                 }
00427 //              printf("coilmap %-7s  %d%% %ld seconds\r",
00428 //                      name.c_str(),(100*(i+1))/nR,(long)(BLTime::time()-start));
00429 //              fflush(stdout);
00430         }
00431         printf("coilmap %-7s  DONE %ld seconds\n",
00432                 name.c_str(),(long)(BLTime::time()-start)); 
00433         fflush(stdout);
00434 
00435         // write the map
00436         if(filename != "") {
00437 #ifdef WIN32
00438                 FILE *out = fopen(filename.c_str(),"wb");
00439 #else
00440                 FILE *out = fopen(filename.c_str(),"w");
00441 #endif
00442                 if(out) {
00443                         FileHeader fh;
00444                         fh.magic = MAGIC;
00445                         fh.nR = nR;
00446                         fh.nZ = nZ;
00447                         fh.nSheets = nSheets;
00448                         fh.innerRadius = innerRadius;
00449                         fh.outerRadius = outerRadius;
00450                         fh.length = length;
00451                         fh.dR = dR;
00452                         fh.dZ = dZ;
00453                         fh.error = err;
00454                         if(fwrite(&fh,sizeof(fh),1,out) != 1 ||
00455                            fwrite(mapBr,sizeof(float),nR*nZ,out) != (size_t)nR*nZ ||
00456                            fwrite(mapBz,sizeof(float),nR*nZ,out) != (size_t)nR*nZ) {
00457                                 printf("coilmap %-7s ERROR "
00458                                         "writing file '%s'\n",
00459                                         name.c_str(),filename.c_str());
00460                         }
00461                         fclose(out);
00462                         printf("coilmap %-7s wrote file '%s'   %lu bytes\n",
00463                                 name.c_str(),filename.c_str(),
00464                                 (long)(sizeof(fh)+sizeof(float)*2*nR*nZ));
00465                 }
00466         }
00467 
00468         goodMap = true;
00469         minZ = -maxZ;
00470         reflectZ = true;
00471         currentOfMap = 1.0;
00472 }

void BLCoil::readMapFile (  ) 

readMapFile() will read the mapFile.

References currentOfMap, dR, dZ, goodMap, mapBr, mapBz, mapFile, maxR, maxZ, minZ, nR, nZ, BLCommand::parseArgs(), BLCommand::printError(), and reflectZ.

Referenced by generateFieldMap().

00475 {
00476         FILE *in = fopen(mapFile.c_str(),"r");
00477         if(!in) {
00478                 BLCommand::printError("Cannot open mapFile '%s'\n",mapFile.c_str());
00479                 return;
00480 error:
00481                 BLCommand::printError("Syntax error in mapFile '%s'\n",mapFile.c_str());
00482                 return;
00483         }
00484 
00485         char line[512];
00486 
00487         // read first line (parameters of the map)
00488         // units are millimeters, Tesla, and Amperes/mm^2.
00489         do {
00490                 if(!fgets(line,sizeof(line),in)) goto error;
00491         } while(line[0] == '#');
00492 
00493         BLArgumentVector argv;
00494         BLArgumentMap argm;
00495         if(BLCommand::parseArgs(line,argv,argm)) goto error;
00496 
00497         // sample parameter line:
00498         // z0=0.0 dz=2.0 nz=1501 dr=5.0 nr=13 reflectZ=1 current=-101.1
00499         G4double z0 = atof(argm["z0"].c_str())*mm;
00500         dZ = atof(argm["dz"].c_str())*mm;
00501         nZ = atoi(argm["nz"].c_str());
00502         dR = atof(argm["dr"].c_str())*mm;
00503         nR = atoi(argm["nr"].c_str());
00504         reflectZ = (atoi(argm["reflectZ"].c_str()) != 0);
00505         currentOfMap = atof(argm["current"].c_str());
00506         maxR = (nR-1)*dR;
00507         maxZ = z0 + (nZ-1)*dZ;
00508         if(reflectZ) {
00509                 minZ = -maxZ;
00510                 if(z0 != 0.0) goto error;
00511         } else {
00512                 minZ = z0;
00513         }
00514         if(argv.size() > 0 || nZ <= 0 || nR <= 0 || maxR <= 0.0 ||
00515                                         maxZ <= 0.0 || currentOfMap == 0.0)
00516                 goto error;
00517         if(mapBr) delete[] mapBr;
00518         if(mapBz) delete[] mapBz;
00519         mapBr = new float[nZ*nR];
00520         mapBz = new float[nZ*nR];
00521         if(!mapBr || !mapBz) {
00522                 G4Exception("coil","Out of memory",FatalException,"");
00523         }
00524 
00525         // read the map -- there are two maps, Bz and Br, each introduced
00526         // by a line with its name in column 1. Each map consists of nZ
00527         // lines of nR floats.
00528         int i=-1;
00529         float *map=0;
00530         while(fgets(line,sizeof(line),in)) {
00531                 if(line[0] == '#') continue;
00532                 if(strncmp(line,"Bz",2) == 0) {
00533                         if(i != -1 && i != nZ) goto error;
00534                         i = 0;
00535                         map = mapBz;
00536                         continue;
00537                 } else if(strncmp(line,"Br",2) == 0) {
00538                         if(i != -1 && i != nZ) goto error;
00539                         i = 0;
00540                         map = mapBr;
00541                         continue;
00542                 }
00543                 if(i < 0 || i >= nZ || !map) goto error;
00544                 char *p = line;
00545                 for(int j=0; j<nR; ++j) {
00546                         char *q=0;
00547                         if(*p == '\0') goto error;
00548                         *map++ = strtod(p,&q)*tesla;
00549                         if(q == 0 || p == q) goto error;
00550                         p = q;
00551                 }
00552                 ++i;
00553         }
00554         if(i != nZ) goto error;
00555         fclose(in);
00556         goodMap = true; 
00557 }

void BLCoil::displayMapValues ( G4double  r,
G4double  z 
)

displayMapValues() will display the 4 map values around a point.

References computeError(), dR, dZ, getUnitField(), goodMap, innerRadius, length, mapBr, mapBz, maxR, name, norm, nR, nZ, and outerRadius.

00602 {
00603         if(!goodMap) {
00604                 printf("BLCoil '%s' has no good map\n",name.c_str());
00605                 return;
00606         }
00607         if(z < 0.0) {
00608                 printf("z must be >= 0\n");
00609                 return;
00610         }
00611 
00612         BLCoil best("temp",innerRadius,outerRadius,length,99,0.0,maxR,maxZ);
00613         G4double Br,Bz;
00614         getUnitField(r,z,Br,Bz);
00615 
00616         int ii = (int)(r/dR);
00617         int jj = (int)(z/dZ);
00618         if(ii+1 >= nR || jj+1 >= nZ) {
00619                 printf("out of range\n");
00620                 return;
00621         }
00622         printf("r=%.3f z=%.3f Bz=%.6f T  Br=%.6f T  Berr=%.6f T\n",
00623                         r,z,Bz/tesla,Bz/tesla,
00624                         computeError(r,z,best,false)/norm/tesla);
00625         G4double bzmin=Bz, bzmax=Bz, bzavg=0.0;
00626         G4double brmin=Br, brmax=Br, bravg=0.0;
00627         for(int i=ii; i<=ii+1; ++i) {
00628             for(int j=jj; j<=jj+1; ++j) {
00629                 if(bzmin > mapBz[j*nR+i]) bzmin = mapBz[j*nR+i];
00630                 if(bzmax < mapBz[j*nR+i]) bzmax = mapBz[j*nR+i];
00631                 if(brmin > mapBr[j*nR+i]) brmin = mapBr[j*nR+i];
00632                 if(brmax < mapBr[j*nR+i]) brmax = mapBr[j*nR+i];
00633                 bzavg += mapBz[j*nR+i]/4.0;
00634                 bravg += mapBr[j*nR+i]/4.0;
00635                 printf("Grid: r=%.3f z=%.3f Bz=%.6f T  Br=%.6f T\n",
00636                         dR*i,dZ*j,mapBz[j*nR+i]/tesla,mapBr[j*nR+i]/tesla);
00637             }
00638         }
00639         printf("BzVariation=%.4f BrVariation=%.4f (fractions of avg)\n",
00640                 (bzmax-bzmin)/bzavg,(brmax-brmin)/bravg);
00641 }

void BLCoil::getUnitField ( G4double  r,
G4double  z,
G4double &  Br,
G4double &  Bz 
) [private]

getUnitField() will return Br and Bz for unit current.

References addField().

Referenced by computeError(), determineMaxR(), determineMaxZ(), displayMapValues(), and generateFieldMap().

00644 {
00645         G4double point[4];
00646         point[0] = point[1] = point[2] = point[3] = 0.0;
00647         G4double f[6];
00648         f[0]=f[1]=f[2]=f[3]=f[4]=f[5]=f[6]=0.0;
00649         point[0] = r;
00650         point[2] = z;
00651         addField(point,f,1.0);
00652         Br = f[0];
00653         Bz = f[2];
00654 }

void BLCoil::determineMaxR (  )  [private]

determineMaxR() will determine maxR based on tolerance. Uses nSheets=99 to determine center field, and walks out far enough so (Bz/Bz0)<0.5*tolerance.

References getUnitField(), innerRadius, length, maxR, name, norm, outerRadius, and tolerance.

Referenced by generateFieldMap().

00657 {
00658         G4double Br,Bz;
00659         BLCoil best("temp",innerRadius,outerRadius,length,99,0.0,
00660                                         10.0*outerRadius,100.0*outerRadius);
00661         if(norm == 0.0) {
00662                 best.getUnitField(0.0,0.0,Br,Bz);
00663                 norm = 1.0/Bz;
00664         }
00665 
00666         // step out in maxR until 0.5*tolerance is achieved
00667         for(maxR=outerRadius+2.0*innerRadius;
00668             maxR<=outerRadius+32.0*innerRadius;
00669             maxR+=innerRadius) {
00670                 best.getUnitField(maxR,0.0,Br,Bz);
00671                 Bz = fabs(Bz);
00672                 if(Bz*norm < 0.5*tolerance) break;
00673         }
00674         if(maxR <= outerRadius+32.0*innerRadius) {
00675                 printf("BLCoil::determineMaxR '%s'  maxR=%.1f err=%.6f\n",
00676                                         name.c_str(),maxR,Bz*norm);
00677         } else {
00678                 G4Exception("coilmap determineMaxR",
00679                                         "Failed to achieve required accuracy",
00680                                         FatalException, "");
00681         }
00682 }

void BLCoil::determineMaxZ (  )  [private]

determineMaxZ() will determine maxZ based on tolerance. Uses nSheets=99 to determine on-axis field, and walks out far enough so (Bz/Bz0)<0.5*tolerance.

References getUnitField(), innerRadius, length, maxR, name, norm, outerRadius, and tolerance.

Referenced by generateFieldMap().

00685 {
00686         G4double Br,Bz;
00687         BLCoil best("temp",innerRadius,outerRadius,length,99,0.0,maxR,
00688                                                         100.0*outerRadius);
00689         if(norm == 0.0) {
00690                 best.getUnitField(0.0,0.0,Br,Bz);
00691                 norm = 1.0/Bz;
00692         }
00693 
00694         // step out in maxZ until 0.5*tolerance is achieved
00695         for(maxZ=length/2.0+4.0*innerRadius; maxZ<=length/2.0+32.0*innerRadius;
00696                                                         maxZ+=innerRadius) {
00697                 best.getUnitField(0.0,maxZ,Br,Bz);
00698                 if(Bz*norm < 0.5*tolerance) break;
00699         }
00700         if(maxZ <= length/2.0+32.0*innerRadius) {
00701                 printf("BLCoil::determineMaxZ '%s'  maxZ=%.1f err=%.6f\n",
00702                                         name.c_str(),maxZ,Bz*norm);
00703         } else {
00704                 G4Exception("coilmap determineMaxZ",
00705                                         "Failed to achieve required accuracy",
00706                                         FatalException, "");
00707         }
00708 }

void BLCoil::determineNsheets (  )  [private]

determineNsheets() will determine nSheets, given maxZ and tolerance. Increases nSheets until maxError < tolerance/4 (the other 3/4 of tolerance is for mapping errors). Checks just a handful of points selected to be representative.

References computeError(), exclude, innerRadius, length, maxR, name, nSheets, outerRadius, sheetDR, sheetR0, and tolerance.

Referenced by generateFieldMap().

00711 {
00712         BLCoil best("temp",innerRadius,outerRadius,length,99,0.0,maxR,maxZ);
00713 
00714         G4double exclude = 0.1 * innerRadius;
00715         G4double err = 0.0;
00716         const int MAX_SHEETS=40;
00717         for(nSheets=2; nSheets<=MAX_SHEETS; nSheets+=2) {
00718                 sheetDR = (outerRadius-innerRadius) / nSheets;
00719                 sheetR0 = innerRadius + sheetDR/2.0;
00720                 err = 0.0;
00721                 for(int i=0; i<50; ++i) {
00722                         G4double r = innerRadius - exclude;
00723                         G4double z = G4UniformRand() * length/2.0;
00724                         if(r >= maxR) r = maxR;
00725                         G4double e = computeError(r,z,best,false);
00726                         if(e > err) err = e;
00727                         r = innerRadius + (outerRadius-innerRadius)*G4UniformRand();
00728                         if(r >= maxR) continue;
00729                         z = length/2.0 + exclude;
00730                         e = computeError(r,z,best,false);
00731                         if(e > err) err = e;
00732                         if(err > tolerance/4.0) break;
00733                 }
00734                 if(err <= tolerance/4.0) break;
00735         }
00736 
00737         if(nSheets <= MAX_SHEETS) {
00738                 printf("BLCoil::determineNsheets '%s'  nSheets=%d err=%.6f\n",
00739                                         name.c_str(),nSheets,err);
00740         } else {
00741                 G4Exception("coilmap determineNsheets",
00742                                         "Failed to achieve required accuracy",
00743                                         FatalException, "");
00744         }
00745 }

G4double BLCoil::estimateMapError (  )  [private]

estimateMapError() will estimate the maximum error in mapping, given maxZ, nSheets, dR, dZ, nR, nZ, and an allocated but uninitialized fieldMap. It generates 1000 random points and returns the maximum error; quits early if tolerance is exceeded. Error is (currentMap - best)/best(r=0,z=0), where best is computed with no map and nSheets=99. For each point it generates the 4 surrounding values of fieldMap (this is faster than generating the entire map first). Returns the maximum error of either Bz or Br, normalized to Bz(r=0,z=0,nSheets=99).

References computeError(), exclude, innerRadius, length, maxR, outerRadius, and tolerance.

Referenced by generateFieldMap().

00748 {
00749         BLCoil best("temp",innerRadius,outerRadius,length,99,0.0,maxR,maxZ);
00750 
00751         // generate 1000 random positions, "close"
00752         // to the coil in z, but exclude the coil (and nearby).
00753         G4double exclude = 0.1 * innerRadius;
00754         G4double err = 0.0;
00755         G4double genZ = length;
00756         if(length/2.0+exclude+10.0*mm > genZ) genZ = length/2.0+exclude+10.0*mm;
00757         for(int i=0; i<1000; ++i) {
00758                 G4double r, z;
00759                 do {
00760                         r = G4UniformRand() * maxR;
00761                         z = G4UniformRand() * genZ;
00762                 } while(z < length/2+exclude &&
00763                         r > innerRadius-exclude &&
00764                         r < outerRadius+exclude);
00765                 G4double e = computeError(r,z,best,true);
00766                 if(e > err) err = e;
00767                 if(err > tolerance) {
00768                         break;
00769                 }
00770 //              if(i%10 == 0)
00771 //                      printf("BLCoil::estimateMapError nR=%d nZ=%d %d%%\r",
00772 //                              nR,nZ,(100*i)/1000), fflush(stdout);
00773         }
00774 
00775         return err;
00776 }

G4double BLCoil::computeError ( G4double  r,
G4double  z,
BLCoil best,
G4bool  makeMap 
) [private]

computeError() computes the error for a single point. Error is (currentMap - best)/best(r=0,z=0), where best should be an identical BLCoil with no map and nSheets=99. If makeMap is true, it generates the 4 surrounding values of the fieldMap.

References BLAssert, dR, dZ, getUnitField(), goodMap, mapBr, mapBz, maxR, norm, nR, and nZ.

Referenced by determineNsheets(), displayMapValues(), and estimateMapError().

00780 {
00781         G4double Br,Bz;
00782         if(z < -maxZ || z > maxZ || r > maxR) return 0.0;
00783         G4bool originalGoodMap = goodMap;
00784 
00785         if(norm == 0.0) {
00786                 best.getUnitField(0.0,0.0,Br,Bz);
00787                 norm = 1.0/Bz;
00788         }
00789 
00790         if(makeMap) {
00791                 // generate fieldMap for the 4 surrounding grid points
00792                 BLAssert(mapBz != 0 && mapBr != 0 && nR > 0 && nZ > 0);
00793                 BLAssert(z >= 0.0);
00794                 goodMap = false;
00795                 int i = (int)(r/dR);
00796                 int j = (int)(z/dZ);
00797                 BLAssert(i >= 0 && i < nR-1 && j >= 0 && j < nZ-1);
00798         
00799                 getUnitField(i*dR,j*dZ,Br,Bz);
00800                 mapBz[j*nR+i] = Bz;
00801                 mapBr[j*nR+i] = Br;
00802 
00803                 getUnitField((i+1)*dR,j*dZ,Br,Bz);
00804                 mapBz[j*nR+(i+1)] = Bz;
00805                 mapBr[j*nR+(i+1)] = Br;
00806         
00807                 getUnitField(i*dR,(j+1)*dZ,Br,Bz);
00808                 mapBz[(j+1)*nR+i] = Bz;
00809                 mapBr[(j+1)*nR+i] = Br;
00810 
00811                 getUnitField((i+1)*dR,(j+1)*dZ,Br,Bz);
00812                 mapBz[(j+1)*nR+(i+1)] = Bz;
00813                 mapBr[(j+1)*nR+(i+1)] = Br;
00814 
00815                 goodMap = true;
00816         }
00817 
00818         G4double bestBr,bestBz;
00819         best.getUnitField(r,z,bestBr,bestBz);
00820         getUnitField(r,z,Br,Bz);
00821         G4double eBr = fabs(Br-bestBr)*norm;
00822         G4double eBz = fabs(Bz-bestBz)*norm;
00823 
00824         goodMap = originalGoodMap;
00825         return (eBr>eBz ? eBr : eBz);
00826 }

void BLCoil::getSheetField ( G4double  r,
G4double  z,
G4double &  Br,
G4double &  Bz,
G4double  sheetR,
G4double  sheetLen,
G4double  currentAmpPerMm 
) const [private]

getSheetField() returns the B field from an infinitesimally-thin sheet of current. Arguments: r and z are the cylindrical coordinates of the point in question relative to center of the coil (axis along z), mm. Br and Bz return the computed B field at that point (geant4 units) sheetR is the radius of the current sheet (mm) sheetLen is the length of the current sheet (mm) currentAmpPerMm is the current of the sheet (Amp per linear mm)

Referenced by addField().

00874 {
00875   // TJR: within this routine the sheet extends from z=0 to z=sheetLen,
00876   //      externally it is centered at z=0.
00877   z += sheetLen/2.0;
00878 
00879 //printf("BLCoil::getSheetField r=%.6g z=%.6g sheetR=%.6g sheetLen=%.6g\n",r,z,sheetR,sheetLen); fflush(stdout);
00880   G4double k; 
00881 
00882   G4double rposition = r/meter;
00883   G4double zposition = z/meter;
00884 
00885   G4double rad = sheetR/meter;
00886   G4double len = sheetLen/meter;
00887   G4double cur = currentAmpPerMm;
00888 
00889   //  Left-end of sheet
00890 
00891   G4double rho = rposition;
00892   z = -zposition;
00893   
00894   G4double r1 = sqrt( pow(rad + rho,2) + z*z );
00895   k = 2.0 / r1 * sqrt( rad * rho );
00896   G4double c2 = -4.0 * rad*rho / pow(rad+rho,2);
00897 
00898   G4double f1 = z * rad / ((rad + rho) * r1);
00899   G4double f2 = (rad - rho) / (2.0 * rad);
00900 
00901 //printf("gsl_sf_ellint_E k=%.6g\n",k); fflush(stdout);
00902   G4double elle = gsl_sf_ellint_E(pi/2.0,k,GSL_PREC_DOUBLE);
00903 //printf("gsl_sf_ellint_F k=%.6g\n",k); fflush(stdout);
00904   G4double ellf = gsl_sf_ellint_F(pi/2.0,k,GSL_PREC_DOUBLE);
00905 //printf("gsl_sf_ellint_P k=%.6g c2=%.6g\n",k,c2); fflush(stdout);
00906   G4double ellpi = gsl_sf_ellint_P(pi/2.0,k,c2,GSL_PREC_DOUBLE);
00907 
00908   G4double bz1 = f1 * ( ellf + f2 * ( ellpi - ellf ) );
00909 
00910   G4double br1;
00911 
00912   if( rho != 0.0 ) {
00913     f1 = r1 / (4.*rho);
00914     br1 = f1 * ( 2. * ( ellf - elle ) - k * k * ellf );
00915   }
00916   else {
00917     br1 = 0.0;
00918   }
00919 
00920   G4double bz = -bz1;
00921   G4double br = -br1;      
00922 
00923   //  Right-end of sheet
00924       
00925   z = z + len;
00926   r1 = sqrt( pow(rad + rho,2) + z*z );
00927   k = 2.0 / r1 * sqrt( rad * rho );
00928   c2 = -4.0 * rad * rho / pow(rad + rho,2);
00929 
00930   f1 = z * rad / ( (rad + rho) * r1);
00931   f2 = (rad - rho) / (2.0 * rad);
00932 
00933 //printf("gsl_sf_ellint_E k=%.6g\n",k); fflush(stdout);
00934   elle = gsl_sf_ellint_E(pi/2.0,k,GSL_PREC_DOUBLE);
00935 //printf("gsl_sf_ellint_F k=%.6g\n",k); fflush(stdout);
00936   ellf = gsl_sf_ellint_F(pi/2.0,k,GSL_PREC_DOUBLE);
00937 //printf("gsl_sf_ellint_P k=%.6g c2=%.6g\n",k,c2); fflush(stdout);
00938   ellpi = gsl_sf_ellint_P(pi/2.0,k,c2,GSL_PREC_DOUBLE);
00939 
00940   bz1 = f1 * ( ellf + f2 * ( ellpi - ellf ) );
00941 
00942   if ( rho != 0.0 ) {
00943     f1 = r1 / (4.0 * rho);
00944     br1 = f1 * ( 2.0 * ( ellf - elle ) - k * k * ellf );
00945   }      
00946   else {
00947     br1 = 0.0;
00948   }
00949 
00950   bz = bz + bz1;       // note change of sign
00951   br = br + br1;
00952 
00953   G4double permfactor = 4.0e-7;
00954 
00955   Br = permfactor * cur * br;
00956   Bz = permfactor * cur * bz;
00957 
00958  }


Friends And Related Function Documentation

friend class BLCMDcoil [friend]

friend class BLCMDsolenoid [friend]

friend class SolenoidField [friend]


Member Data Documentation

std::map< G4String, BLCoil * > BLCoil::mapCoil [static, private]

Referenced by BLCMDcoil::command(), and find().

G4String BLCoil::name [private]

G4double BLCoil::innerRadius [private]

G4double BLCoil::outerRadius [private]

G4double BLCoil::length [private]

G4int BLCoil::nSheets [private]

G4String BLCoil::material [private]

G4double BLCoil::tolerance [private]

G4double BLCoil::maxR [private]

G4double BLCoil::minZ [private]

G4double BLCoil::maxZ [private]

G4double BLCoil::dR [private]

G4double BLCoil::dZ [private]

G4int BLCoil::nR [private]

G4int BLCoil::nZ [private]

G4String BLCoil::filename [private]

G4String BLCoil::mapFile [private]

G4int BLCoil::exactComputation [private]

float* BLCoil::mapBr [private]

float* BLCoil::mapBz [private]

G4double BLCoil::sheetR0 [private]

G4double BLCoil::sheetDR [private]

G4double BLCoil::norm [private]

G4bool BLCoil::goodMap [private]

G4bool BLCoil::reflectZ [private]

G4double BLCoil::currentOfMap [private]


The documentation for this class was generated from the following files:
g4beamline