00001
00002
00003
00004
00005 #include "globals.hh"
00006 #include "BDSXYMagField.hh"
00007 #include <fstream>
00008
00009 using namespace std;
00010
00011 G4double GetNearestValue(vector<struct XYFieldRecord> fieldValues, G4double x, G4double y,
00012 G4double &bx,G4double &by, G4double &bz);
00013
00014 BDSXYMagField::BDSXYMagField(G4String fname) :
00015 nX(0), nY(0), itsFileName(fname)
00016 {
00017 }
00018
00019 BDSXYMagField::~BDSXYMagField()
00020 {
00021
00022 }
00023
00024 G4bool BDSXYMagField::DoesFieldChangeEnergy() const
00025 {
00026 return false;
00027 }
00028
00029 G4int BDSXYMagField::ReadFile(G4String fname)
00030 {
00031 G4cout<<"reading file "<<fname<<G4endl;
00032
00033 struct XYFieldRecord rec;
00034
00035 ifstream bmapif;
00036 bmapif.open(fname);
00037
00038 while(bmapif.good())
00039 {
00040 bmapif>>rec.x>>rec.y>>rec.Bx>>rec.By>>rec.Bz;
00041
00042 if(!bmapif.good()) break;
00043
00044 itsFieldValues.push_back(rec);
00045 }
00046
00047 bmapif.close();
00048
00049 G4cout<<"done"<<G4endl;
00050
00051 return 0;
00052
00053 }
00054
00055
00056 void BDSXYMagField::Prepare(G4VPhysicalVolume *referenceVolume)
00057 {
00058 G4cout<<"BDSElement:: create XY field mesh"<<G4endl;
00059
00060 ReadFile(itsFileName);
00061
00062 if( itsFieldValues.size() == 0 )
00063 {
00064 G4cerr<<"empty bmap file "<<itsFileName<<" exiting..."<<G4endl;
00065 exit(1);
00066 }
00067
00068 const G4RotationMatrix* Rot=referenceVolume->GetFrameRotation();
00069 const G4ThreeVector Trans=referenceVolume->GetFrameTranslation();
00070
00071 G4ThreeVector B;
00072
00073
00074
00075
00076 vector<struct XYFieldRecord>::iterator it, itt;
00077
00078
00079 double xmax=0, ymax=0;
00080
00081 for(it=itsFieldValues.begin();it!=itsFieldValues.end();it++)
00082 {
00083 if( fabs((*it).x ) > xmax ) xmax = fabs((*it).x);
00084 if( fabs((*it).y ) > ymax) ymax = fabs((*it).y);
00085 }
00086
00087
00088
00089
00090 double hx=xmax, hxold=xmax, hxmax=0;
00091 double hy=ymax, hyold=ymax, hymax=0;
00092
00093 xHalf = xmax / 2;
00094 yHalf = ymax / 2;
00095
00096 for(it=++itsFieldValues.begin();it!=itsFieldValues.end();it++)
00097 {
00098
00099 for(itt=itsFieldValues.begin();itt!=itsFieldValues.end();itt++)
00100 {
00101
00102
00103 hxold = fabs((*it).x - (*itt).x);
00104 if( (hxold > 1.0e-11*m)&&(hxold<hx) ) hx = hxold;
00105
00106 hyold = fabs((*it).y - (*itt).y);
00107 if( (hyold > 1.0e-11*m)&&(hyold<hy) ) hy = hyold;
00108
00109 }
00110 }
00111
00112 hxmax = hx; hymax = hy;
00113
00114 G4cout<<"h ="<<hx<<":"<<hy<<":"<<G4endl;
00115 G4cout<<"xmax ="<<xmax<<":"<<ymax<<":"<<G4endl;
00116
00117
00118
00119
00120 G4int nX = static_cast<int> ( 2*xHalf / hx ) + 1;
00121 G4int nY = static_cast<int> ( 2*yHalf / hy ) + 1;
00122
00123
00124 G4cout<<"N ="<<nX<<":"<<nY<<G4endl;
00125
00126 AllocateMesh(nX,nY);
00127
00128 SetOriginRotation(*Rot);
00129 SetOriginTranslation(Trans);
00130
00131 G4double bx, by, bz, x, y;
00132
00133 for(int i=0; i<nX;i++)
00134 for(int j=0;j<nY;j++)
00135 {
00136 x = i * hx - xHalf;
00137 y = j * hy - yHalf;
00138
00139
00140
00141
00142
00143 G4double dist = GetNearestValue(itsFieldValues,x,y,bx,by,bz);
00144
00145 G4double tol = 10 * hx;
00146
00147 if(dist < tol) {
00148 SetBx(i,j,bx * tesla);
00149 SetBy(i,j,by * tesla);
00150 SetBz(i,j,bz * tesla);
00151
00152 } else {
00153 SetBx(i,j,0.);
00154 SetBy(i,j,0.);
00155 SetBz(i,j,0.);
00156 }
00157 }
00158
00159
00160
00161
00162 G4cout<<"writing test file"<<G4endl;
00163
00164 ofstream testf("btest.dat");
00165
00166 for(int i=0; i<nX;i++)
00167 for(int j=0;j<nY;j++)
00168 {
00169 testf<<i<<" "<<j<<" "" "<<
00170 GetBx(i,j)<<" "<<
00171 GetBy(i,j)<<" "<<
00172 GetBz(i,j)<<endl;
00173 }
00174
00175 testf.close();
00176
00177 }
00178
00179
00180 void BDSXYMagField::GetFieldValue(const G4double Point[4], G4double *Bfield ) const
00181 {
00182 G4double bx=0, by=0, bz;
00183 G4int i=0,j=0;
00184
00185 G4ThreeVector local;
00186
00187 if( (nX <= 0) || (nY<=0) )
00188 {
00189 G4cout<<"no mesh"<<G4endl;
00190 bx = by = 0;
00191 }
00192 else
00193 {
00194 local[0] = Point[0] - translation[0];
00195 local[1] = Point[1] - translation[1];
00196 local[2] = Point[2] - translation[2];
00197
00198 local *= rotation;
00199
00200 i = (G4int)(nX/2.0 + nX * local[0] / (2.0 * xHalf));
00201 j = (G4int)(nY/2.0 + nY * local[1] / (2.0 * yHalf));
00202
00203 bx = Bx[i][j];
00204 by = By[i][j];
00205 bz = Bz[i][j];
00206 }
00207
00208
00209 Bfield[0] = bx;
00210 Bfield[1] = by;
00211
00212
00213 Bfield[3] = 0;
00214 Bfield[4] = 0;
00215 Bfield[5] = 0;
00216
00217
00218
00219
00220 }
00221
00222 int BDSXYMagField::AllocateMesh(int nx, int ny)
00223 {
00224 nX = nx;
00225 nY = ny;
00226
00227 Bx = new double*[nX];
00228 for(int i=0;i<nX;i++)
00229 {
00230 Bx[i] = new double[nY];
00231 }
00232
00233 By = new double*[nX];
00234 for(int i=0;i<nX;i++)
00235 {
00236 By[i] = new double[nY];
00237 }
00238
00239 Bz = new double*[nX];
00240 for(int i=0;i<nX;i++)
00241 {
00242 Bz[i] = new double[nY];
00243 }
00244
00245 return 0;
00246 }
00247
00248 inline
00249 void BDSXYMagField::SetBx(int i,int j,double val)
00250 {
00251 Bx[i][j] = val;
00252 }
00253
00254 inline
00255 void BDSXYMagField::SetBy(int i,int j,double val)
00256 {
00257 By[i][j] = val;
00258 }
00259
00260
00261 inline
00262 void BDSXYMagField::SetBz(int i,int j,double val)
00263 {
00264 Bz[i][j] = val;
00265 }
00266
00267 inline
00268 G4double BDSXYMagField::GetBx(int i,int j)
00269 {
00270 return Bx[i][j];
00271 }
00272
00273 inline
00274 G4double BDSXYMagField::GetBy(int i,int j)
00275 {
00276 return By[i][j];
00277 }
00278
00279 inline
00280 G4double BDSXYMagField::GetBz(int i,int j)
00281 {
00282 return Bz[i][j];
00283 }
00284
00285
00286 G4double GetNearestValue(vector<struct XYFieldRecord> fieldValues, G4double x, G4double y,
00287 G4double &bx,G4double &by, G4double &bz)
00288 {
00289 vector<struct XYFieldRecord>::iterator it;
00290
00291 G4double dist = 10.e+10;
00292
00293 for(it = fieldValues.begin(); it!=fieldValues.end();it++)
00294 {
00295 dist = sqrt( (x-(*it).x)*(x-(*it).x) + (y-(*it).y)*(y-(*it).y));
00296 bx = (*it).Bx;
00297 by = (*it).By;
00298 bz = (*it).Bz;
00299 }
00300
00301 return dist;
00302
00303 }
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505