source: trunk/examples/novice/gemc/src/MagneticField.cc@ 1190

Last change on this file since 1190 was 807, checked in by garnier, 17 years ago

update

File size: 26.0 KB
Line 
1
2
3
4
5
6
7
8// %%%%%%%%%%
9// G4 headers
10// %%%%%%%%%%
11#include "G4UniformMagField.hh"
12#include "G4PropagatorInField.hh"
13#include "G4TransportationManager.hh"
14#include "G4Mag_UsualEqRhs.hh"
15#include "G4MagIntegratorStepper.hh"
16#include "G4ChordFinder.hh"
17#include "G4ClassicalRK4.hh"
18#include "G4HelixSimpleRunge.hh"
19
20// %%%%%%%%%%
21// Qt headers
22// %%%%%%%%%%
23#include <QtSql>
24
25// %%%%%%%%%%%%%
26// gemc headers
27// %%%%%%%%%%%%%
28#include "detector.h"
29#include "MagneticField.h"
30#include "usage.h"
31
32map<string, MagneticField> get_magnetic_Fields(gemc_opts Opt)
33{
34 string hd_msg = Opt.args["LOG_MSG"].args + " Magnetic Field >> " ;
35 double MGN_VERBOSITY = Opt.args["MGN_VERBOSITY"].arg;
36 string database = Opt.args["DATABASE"].args;
37 string dbtable = "magnetic_fields";
38
39 map<string, MagneticField> FieldMap;
40
41 QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
42 db.setHostName("clasdb.jlab.org");
43 db.setDatabaseName(database.c_str());
44 db.setUserName("clasuser");
45 bool ok = db.open();
46
47 if(!ok)
48 {
49 cout << hd_msg << " Database not connected. Exiting." << endl;
50 exit(-1);
51 }
52
53 MagneticField magneticField;
54 QSqlQuery q;
55 string dbexecute = "select name, type, magnitude, swim_method, description from " + dbtable ;
56 q.exec(dbexecute.c_str());
57
58 if(MGN_VERBOSITY>2)
59 cout << hd_msg << " Available Magnetic Fields: " << endl << endl;
60
61 while (q.next())
62 {
63 magneticField.name = TrimSpaces(q.value(0).toString().toStdString());
64 magneticField.type = q.value(1).toString().toStdString();
65 magneticField.magnitude = q.value(2).toString().toStdString();
66 magneticField.swim_method = q.value(3).toString().toStdString();
67 magneticField.description = q.value(4).toString().toStdString();
68
69 // Sets MFM pointer to NULL
70 magneticField.init_MFM();
71 magneticField.gemcOpt = Opt;
72
73 FieldMap[magneticField.name] = magneticField;
74
75 if(MGN_VERBOSITY>2)
76 {
77 cout << " ";
78 cout.width(15);
79 cout << magneticField.name << " | ";
80 cout << magneticField.description << endl;
81 cout << " ";
82 cout.width(15);
83 cout << magneticField.name << " | type: | ";
84 cout << magneticField.type << endl;
85 cout << " ";
86 cout.width(15);
87 cout << magneticField.name << " | Magnitude: | ";
88 cout << magneticField.magnitude << endl;
89 cout << " ";
90 cout.width(15);
91 cout << magneticField.name << " | Swim Method: | ";
92 cout << magneticField.swim_method << endl;
93 cout << " -------------------------------------------------------------- " << endl;
94 }
95 }
96 db.close();
97
98 cout << endl;
99 db = QSqlDatabase();
100 db.removeDatabase("qt_sql_default_connection");
101
102 return FieldMap;
103}
104
105
106void MagneticField::create_MFM()
107{
108 string hd_msg = gemcOpt.args["LOG_MSG"].args + " Magnetic Field: >> ";
109 double MGN_VERBOSITY = gemcOpt.args["MGN_VERBOSITY"].arg ;
110 string catch_v = gemcOpt.args["CATCH"].args;
111
112 stringstream vars;
113 string var, format, symmetry, MapFile;
114 string var1, var2, dim;
115
116 string integration_method;
117
118 vars << type;
119 vars >> var >> format >> symmetry >> MapFile;
120
121 mappedfield = NULL;
122
123 // %%%%%%%%%%%%%%%%%%%%%%
124 // Uniform Magnetic Field
125 // %%%%%%%%%%%%%%%%%%%%%%
126 if(var == "uniform")
127 {
128 vars.clear();
129 vars << magnitude;
130 double x,y,z;
131 vars >> var; x = get_number(var);
132 vars >> var; y = get_number(var);
133 vars >> var; z = get_number(var);
134 if(MGN_VERBOSITY>3)
135 {
136 cout << hd_msg << " <" << name << "> is a uniform magnetic field type." << endl;
137 cout << hd_msg << " <" << name << "> dimensions:" ;
138 cout << " (" << x/gauss << ", " << y/gauss << ", " << z/gauss << ") gauss." << endl;
139 }
140 G4UniformMagField* magField = new G4UniformMagField(G4ThreeVector((x/gauss)*gauss, (y/gauss)*gauss, (z/gauss)*gauss));
141
142 G4Mag_UsualEqRhs* iEquation = new G4Mag_UsualEqRhs(magField);
143 G4MagIntegratorStepper* iStepper = new G4ClassicalRK4(iEquation);
144 G4ChordFinder* iChordFinder = new G4ChordFinder(magField, 1.0e-2*mm, iStepper);
145
146 MFM = new G4FieldManager(magField, iChordFinder);
147
148 return;
149 }
150
151 // %%%%%%%%%%%%%%%%%%%%%%%
152 // Mapped Field
153 // phi-symmetric
154 // cylindrical coordinates
155 // %%%%%%%%%%%%%%%%%%%%%%%
156 if(var == "mapped" && symmetry == "cylindrical")
157 {
158 vars.clear();
159 vars << magnitude;
160 int TNPOINTS, LNPOINTS;
161 double tlimits[2], llimits[2];
162 double mapOrigin[3];
163 string units[5];
164
165 vars >> var;
166 TNPOINTS = (int) get_number(var);
167 vars >> var1 >> var2 >> dim;
168 tlimits[0] = get_number(var1 + "*" + dim);
169 tlimits[1] = get_number(var2 + "*" + dim);
170 units[0].assign(dim);
171
172
173 vars >> var;
174 LNPOINTS = (int) get_number(var);
175 vars >> var1 >> var2 >> dim;
176 llimits[0] = get_number(var1 + "*" + dim);
177 llimits[1] = get_number(var2 + "*" + dim);
178 units[1].assign(dim);
179
180 // Origin
181 vars >> var ; mapOrigin[0] = get_number(var);
182 vars >> var ; mapOrigin[1] = get_number(var);
183 vars >> var ; mapOrigin[2] = get_number(var);
184 vars >> var ; units[3].assign(var);
185
186 // Field Units
187 vars >> var ; units[4].assign(var);
188
189 vars.clear();
190 vars << swim_method;
191 vars >> integration_method;
192 vars.clear();
193 vars << swim_method;
194 vars >> integration_method;
195 if(MGN_VERBOSITY>3)
196 {
197 cout << hd_msg << " <" << name << "> is a phi-symmetric mapped field in cylindrical coordinates" << endl;;
198 cout << hd_msg << " <" << name << "> has (" << TNPOINTS << ", " << LNPOINTS << ") points." << endl;;
199 cout << hd_msg << " Tranverse Boundaries: (" << tlimits[0]/cm << ", " << tlimits[1]/cm << ") cm." << endl;
200 cout << hd_msg << " Longitudinal Boundaries: (" << llimits[0]/cm << ", " << llimits[1]/cm << ") cm." << endl;
201 cout << hd_msg << " Map Displacement: (" << mapOrigin[0]/cm << ", "
202 << mapOrigin[1]/cm << ", "
203 << mapOrigin[2]/cm << ") cm." << endl;
204 cout << hd_msg << " Integration Method: " << integration_method << endl;
205 cout << hd_msg << " Map Field Units: " << units[4] << endl;
206 cout << hd_msg << " Map File: " << MapFile << endl;
207 }
208 mappedfield = new MappedField(gemcOpt, TNPOINTS, LNPOINTS, tlimits, llimits, MapFile, mapOrigin, units);
209
210 }
211
212 // %%%%%%%%%%%%%%%%%%%%%%%
213 // Mapped Field
214 // phi-segmented
215 // cylindrical coordinates
216 // %%%%%%%%%%%%%%%%%%%%%%%
217 if(var == "mapped" && symmetry == "phi-segmented")
218 {
219 vars.clear();
220 vars << magnitude;
221 int TNPOINTS, PNPOINTS, LNPOINTS;
222 double plimits[2], tlimits[2], llimits[2];
223 double mapOrigin[3];
224 string units[5];
225
226 vars >> var ;
227 PNPOINTS = (int) get_number(var);
228 vars >> var1 >> var2 >> dim;
229 plimits[0] = get_number(var1 + "*" + dim);
230 plimits[1] = get_number(var2 + "*" + dim);
231 units[0].assign(dim);
232
233 vars >> var ;
234 TNPOINTS = (int) get_number(var);
235 vars >> var1 >> var2 >> dim;
236 tlimits[0] = get_number(var1 + "*" + dim);
237 tlimits[1] = get_number(var2 + "*" + dim);
238 units[1].assign(dim);
239
240 vars >> var ;
241 LNPOINTS = (int) get_number(var);
242 vars >> var1 >> var2 >> dim;
243 llimits[0] = get_number(var1 + "*" + dim);
244 llimits[1] = get_number(var2 + "*" + dim);
245 units[2].assign(dim);
246
247 // Origin
248 vars >> var ; mapOrigin[0] = get_number(var);
249 vars >> var ; mapOrigin[1] = get_number(var);
250 vars >> var ; mapOrigin[2] = get_number(var);
251 vars >> var ; units[3].assign(var);
252
253 // Field Units
254 vars >> var ; units[4].assign(var);
255
256 vars.clear();
257 vars << swim_method;
258 vars >> integration_method;
259 vars.clear();
260 vars << swim_method;
261 vars >> integration_method;
262 double segm_phi_span = 2*(plimits[1] - plimits[0]); // factor of two: the map is assumed to cover half the segment
263 int nsegments = (int) (360.0/(segm_phi_span/deg));
264 if( fabs( segm_phi_span*nsegments/deg - 360 ) > 1.0e-2 )
265 {
266 cout << hd_msg << " <" << name << "> segmentation is wrong: " << nsegments << " segments, each span "
267 << segm_phi_span/deg << ": it doesn't add to 360, but " << segm_phi_span*nsegments/deg << " Exiting." << endl;
268 exit(0);
269
270 }
271 if(MGN_VERBOSITY>3)
272 {
273 cout << hd_msg << " <" << name << "> is a phi-segmented mapped field in cylindrical coordinates" << endl;;
274 cout << hd_msg << " <" << name << "> has (" << PNPOINTS << ", " << TNPOINTS << ", " << LNPOINTS << ") points" << endl;;
275 cout << hd_msg << " Azimuthal Boundaries: (" << plimits[0]/deg << ", " << plimits[1]/deg << ") deg" << endl;
276 cout << hd_msg << " Tranverse Boundaries: (" << tlimits[0]/cm << ", " << tlimits[1]/cm << ") cm" << endl;
277 cout << hd_msg << " Longitudinal Boundaries: (" << llimits[0]/cm << ", " << llimits[1]/cm << ") cm" << endl;
278 cout << hd_msg << " Phi segment span, number of segments: " << segm_phi_span/deg << " deg, " << nsegments << endl;
279 cout << hd_msg << " Map Displacement: (" << mapOrigin[0]/cm << ", "
280 << mapOrigin[1]/cm << ", "
281 << mapOrigin[2]/cm << ") cm" << endl;
282 cout << hd_msg << " Integration Method: " << integration_method << endl;
283 cout << hd_msg << " Map Field Units: " << units[4] << endl;
284 cout << hd_msg << " Map File: " << MapFile << endl;
285 }
286 mappedfield = new MappedField(gemcOpt, TNPOINTS, PNPOINTS, LNPOINTS, tlimits, plimits, llimits, MapFile, mapOrigin, units);
287 mappedfield->segm_phi_span = segm_phi_span;
288 mappedfield->nsegments = nsegments;
289 }
290
291
292 if(integration_method == "RungeKutta")
293 {
294 // specialized equations for mapped magnetic field
295
296 G4Mag_UsualEqRhs* iEquation = new G4Mag_UsualEqRhs(mappedfield);
297 G4MagIntegratorStepper* iStepper = new G4HelixSimpleRunge(iEquation);
298 G4ChordFinder* iChordFinder = new G4ChordFinder(mappedfield, 1.0e-2*mm, iStepper);
299
300 MFM = new G4FieldManager(mappedfield, iChordFinder);
301 MFM->SetDeltaOneStep(1*mm);
302 MFM->SetDeltaIntersection(1*mm);
303 }
304}
305
306MappedField::MappedField(){;}
307MappedField::~MappedField(){;}
308
309// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
310// Constructor for phi-symmetric field in cylindrical coordinates
311// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
312MappedField::MappedField(gemc_opts Opt, int TNPOINTS, int LNPOINTS, double tlimits[2], double llimits[2],
313 string filename, double origin[3], string units[5])
314{
315 gemcOpt = Opt;
316 string hd_msg = gemcOpt.args["LOG_MSG"].args + " Magnetic Field Constructor: >> ";
317 MGN_VERBOSITY = (int) gemcOpt.args["MGN_VERBOSITY"].arg ;
318
319 mapOrigin[0] = origin[0];
320 mapOrigin[1] = origin[1];
321 mapOrigin[2] = origin[2];
322
323 table_start[0] = tlimits[0];
324 table_start[1] = llimits[0];
325 cell_size[0] = (tlimits[1] - tlimits[0])/( TNPOINTS - 1);
326 cell_size[1] = (llimits[1] - llimits[0])/( LNPOINTS - 1);
327
328 if(MGN_VERBOSITY>3)
329 {
330 cout << hd_msg << " The transverse cell size is: " << cell_size[0]/cm << " cm" << endl
331 << hd_msg << " and the longitudinal cell size is: " << cell_size[1]/cm << " cm" << endl;
332
333 }
334
335 ifstream IN(filename.c_str());
336 if(!IN)
337 {
338 cout << hd_msg << " File " << filename << " could not be opened. Exiting." << endl;
339 exit(0);
340 }
341 cout << hd_msg << " Reading map file: " << filename << "... ";
342
343 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
344 // Setting up storage space for tables
345 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
346 B2DCylT.resize( TNPOINTS );
347 B2DCylL.resize( TNPOINTS );
348 for(int it=0; it<TNPOINTS; it++)
349 {
350 B2DCylT[it].resize(LNPOINTS);
351 B2DCylL[it].resize(LNPOINTS);
352 }
353
354 // %%%%%%%%%%%%%
355 // Filling table
356 // %%%%%%%%%%%%%
357 double TC, LC; // coordinates as read from the map
358 double BT, BL; // transverse and longitudinal magnetic field as read from the map
359 unsigned int IT, IL; // indexes of the vector map
360
361 for(int it=0; it<TNPOINTS; it++)
362 {
363 for(int il=0; il<LNPOINTS; il++)
364 {
365 IN >> TC >> LC >> BT >> BL;
366 if(units[0] == "cm") TC *= cm;
367 else cout << hd_msg << " Dimension Unit " << units[0] << " not implemented yet." << endl;
368 if(units[1] == "cm") LC *= cm;
369 else cout << hd_msg << " Dimension Unit " << units[1] << " not implemented yet." << endl;
370
371 // checking map consistency for longitudinal coordinate
372 if( (llimits[0] + il*cell_size[1] - LC)/LC > 0.001)
373 {
374 cout << hd_msg << il << " longitudinal index wrong. Map point should be " << llimits[0] + il*cell_size[1]
375 << " but it's " << LC << " instead." << endl;
376 }
377
378 IT = (unsigned int) floor( ( TC/mm - table_start[0]/mm + cell_size[0]/mm/2 ) / ( cell_size[0]/mm ) ) ;
379 IL = (unsigned int) floor( ( LC/mm - table_start[1]/mm + cell_size[1]/mm/2 ) / ( cell_size[1]/mm ) ) ;
380
381 if(units[4] == "gauss")
382 {
383 B2DCylT[IT][IL] = BT*gauss;
384 B2DCylL[IT][IL] = BL*gauss;
385 }
386 if(units[4] == "kilogauss")
387 {
388 B2DCylT[IT][IL] = BT*kilogauss;
389 B2DCylL[IT][IL] = BL*kilogauss;
390 }
391 else
392 {
393 cout << hd_msg << " Field Unit " << units[4] << " not implemented yet." << endl;
394 }
395 }
396 // checking map consistency for transverse coordinate
397 if( (tlimits[0] + it*cell_size[0] - TC)/TC > 0.001)
398 {
399 cout << hd_msg << it << " transverse index wrong. Map point should be " << tlimits[0] + it*cell_size[0]
400 << " but it's " << TC << " instead." << endl;
401 }
402 }
403
404 IN.close();
405 cout << " done!" << endl;
406
407}
408
409
410// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
411// Constructor for phi-segmented field in cylindrical coordinates. Field is in cartesian coordinates
412// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
413MappedField::MappedField(gemc_opts Opt, int rNPOINTS, int pNPOINTS, int zNPOINTS, double tlimits[2], double plimits[2], double llimits[2],
414 string filename, double origin[3], string units[5])
415{
416 gemcOpt = Opt;
417 string hd_msg = gemcOpt.args["LOG_MSG"].args + " Magnetic Field Constructor: >> ";
418 MGN_VERBOSITY = (int) gemcOpt.args["MGN_VERBOSITY"].arg ;
419
420 mapOrigin[0] = origin[0];
421 mapOrigin[1] = origin[1];
422 mapOrigin[2] = origin[2];
423
424 table_start[0] = plimits[0];
425 table_start[1] = tlimits[0];
426 table_start[2] = llimits[0];
427 cell_size[0] = (plimits[1] - plimits[0])/( pNPOINTS - 1);
428 cell_size[1] = (tlimits[1] - tlimits[0])/( rNPOINTS - 1);
429 cell_size[2] = (llimits[1] - llimits[0])/( zNPOINTS - 1);
430
431 if(MGN_VERBOSITY>3)
432 {
433 cout << hd_msg << " the phi cell size is: " << cell_size[0]/deg << " degrees" << endl
434 << hd_msg << " The radius cell size is: " << cell_size[1]/cm << " cm" << endl
435 << hd_msg << " and the z cell size is: " << cell_size[2]/cm << " cm" << endl;
436 }
437
438 ifstream IN(filename.c_str());
439 if(!IN)
440 {
441 cout << hd_msg << " File " << filename << " could not be opened. Exiting." << endl;
442 exit(0);
443 }
444 cout << hd_msg << " Reading map file: " << filename << "... ";
445
446
447 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
448 // Setting up storage space for tables
449 // Field[phi][r][z]
450 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
451
452 B3DCylX.resize( pNPOINTS );
453 B3DCylY.resize( pNPOINTS );
454 B3DCylZ.resize( pNPOINTS );
455 for(int ip=0; ip<pNPOINTS; ip++)
456 {
457 B3DCylX[ip].resize( rNPOINTS );
458 B3DCylY[ip].resize( rNPOINTS );
459 B3DCylZ[ip].resize( rNPOINTS );
460 for(int ir=0; ir<rNPOINTS; ir++)
461 {
462 B3DCylX[ip][ir].resize( zNPOINTS );
463 B3DCylY[ip][ir].resize( zNPOINTS );
464 B3DCylZ[ip][ir].resize( zNPOINTS );
465 }
466 }
467
468 // %%%%%%%%%%%%%
469 // Filling table
470 // %%%%%%%%%%%%%
471 double pC, tC, lC; // coordinates as read from the map
472 double Bx, By, Bz; // magnetic field components as read from the map
473 unsigned int It, Ip, Il; // indexes of the vector map
474 for(int ip=0; ip<pNPOINTS; ip++)
475 {
476 for(int it=0; it<rNPOINTS; it++)
477 {
478 for(int il=0; il<zNPOINTS; il++)
479 {
480 IN >> pC >> tC >> lC >> Bx >> By >> Bz;
481
482 if(units[0] == "deg") pC = pC*deg;
483 else cout << hd_msg << " Dimension Unit " << units[0] << " not implemented yet." << endl;
484 if(units[1] == "cm") tC *= cm;
485 else cout << hd_msg << " Dimension Unit " << units[1] << " not implemented yet." << endl;
486 if(units[2] == "cm") lC *= cm;
487 else cout << hd_msg << " Dimension Unit " << units[2] << " not implemented yet." << endl;
488
489 // checking map consistency for longitudinal coordinate
490 if( (llimits[0] + il*cell_size[2] - lC)/lC > 0.001)
491 {
492 cout << hd_msg << il << " longitudinal index wrong. Map point should be " << llimits[0] + il*cell_size[2]
493 << " but it's " << lC << " instead." << endl;
494 }
495
496 Ip = (unsigned int) floor( ( pC/deg - table_start[0]/deg + cell_size[0]/deg/2 ) / ( cell_size[0]/deg ) ) ;
497 It = (unsigned int) floor( ( tC/mm - table_start[1]/mm + cell_size[1]/mm/2 ) / ( cell_size[1]/mm ) ) ;
498 Il = (unsigned int) floor( ( lC/mm - table_start[2]/mm + cell_size[2]/mm/2 ) / ( cell_size[2]/mm ) ) ;
499
500 if(units[4] == "gauss")
501 {
502 B3DCylX[Ip][It][Il] = Bx*gauss;
503 B3DCylY[Ip][It][Il] = By*gauss;
504 B3DCylZ[Ip][It][Il] = Bz*gauss;
505 }
506 if(units[4] == "kilogauss")
507 {
508 B3DCylX[Ip][It][Il] = Bx*kilogauss;
509 B3DCylY[Ip][It][Il] = By*kilogauss;
510 B3DCylZ[Ip][It][Il] = Bz*kilogauss;
511 }
512 else
513 {
514 cout << hd_msg << " Field Unit " << units[4] << " not implemented yet." << endl;
515 }
516
517 if(MGN_VERBOSITY>10)
518 {
519 cout << " phi=" << pC/deg << ", ip=" << Ip << " "
520 << " r=" << tC/cm << ", it=" << It << " "
521 << " z=" << lC/cm << ", iz=" << Il << " "
522 << " Bx=" << B3DCylX[Ip][It][Il]/kilogauss << " "
523 << " By=" << B3DCylY[Ip][It][Il]/kilogauss << " "
524 << " Bz=" << B3DCylZ[Ip][It][Il]/kilogauss << " kilogauss. Map Values: "
525 << " rBx=" << Bx << " "
526 << " rBy=" << By << " "
527 << " rBz=" << Bz << endl;
528
529 }
530
531 }
532
533 // checking map consistency for transverse coordinate
534 if( (tlimits[0] + it*cell_size[1] - tC)/tC > 0.001)
535 {
536 cout << hd_msg << it << " transverse index wrong. Map point should be " << tlimits[0] + it*cell_size[0]
537 << " but it's " << tC << " instead." << endl;
538 }
539
540 }
541
542 // checking map consistency for azimuthal coordinate
543 if( (plimits[0] + ip*cell_size[0] - pC)/pC > 0.001)
544 {
545 cout << hd_msg << ip << " azimuthal index wrong. Map point should be " << plimits[0] + ip*cell_size[1]
546 << " but it's " << pC << " instead." << endl;
547 }
548
549 }
550
551 IN.close();
552 cout << " done!" << endl;
553
554}
555
556
557
558
559// %%%%%%%%%%%%%
560// GetFieldValue
561// %%%%%%%%%%%%%
562void MappedField::GetFieldValue(const double point[3], double *Bfield) const
563{
564
565 double Point[3]; // global coordinates, in mm, after shifting the origin
566 vector<double> Field[3];
567
568 Point[0] = point[0] - mapOrigin[0]/mm;
569 Point[1] = point[1] - mapOrigin[1]/mm;
570 Point[2] = point[2] - mapOrigin[2]/mm;
571
572 Bfield[0] = Bfield[1] = Bfield[2] = 0*gauss;
573
574 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
575 // phi symmetric field in cylindrical coordinates
576 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
577 if(B2DCylT.size() && B2DCylL.size())
578 {
579 double psfield[3] = {0,0,0};
580 unsigned int IT, IL;
581
582 double LC; // longitudinal coordinate of the track in the global coordinate system
583 double TC, phi; // transverse and phy polar 2D coordinates: the map is phi-symmetric. phi is angle in respect to x
584 TC = sqrt(Point[0]*Point[0] + Point[1]*Point[1]);
585 if( TC!=0 ) phi = acos(Point[0]/TC);
586 else phi = 0;
587 LC = Point[2];
588
589 IT = (unsigned int) floor( ( TC - table_start[0]/mm ) / (cell_size[0]/mm) ) ;
590 IL = (unsigned int) floor( ( LC - table_start[1]/mm ) / (cell_size[1]/mm) ) ;
591
592 if( fabs( table_start[0]/mm + IT*cell_size[0]/mm - TC) > fabs( table_start[0]/mm + (IT+1)*cell_size[0]/mm - TC) ) IT++;
593 if( fabs( table_start[1]/mm + IL*cell_size[1]/mm - LC) > fabs( table_start[1]/mm + (IL+1)*cell_size[1]/mm - LC) ) IL++;
594
595
596 // vector sizes are checked on both T and L components
597 // (even if only one is enough)
598 if(IT < B2DCylT.size() && IT < B2DCylL.size())
599 if(IL < B2DCylT[IT].size() && IL < B2DCylL[IT].size() )
600 {
601 psfield[0] = B2DCylT[IT][IL] * cos(phi);
602 psfield[1] = B2DCylT[IT][IL] * sin(phi);
603 psfield[2] = B2DCylL[IT][IL];
604 if(MGN_VERBOSITY>5)
605 {
606 cout << hd_msg << " Phi-Simmetric Field: Cart. and Cyl. coordinates (cm), table indexes, magnetic field values (gauss):" << endl;
607 cout << " x=" << point[0]/cm << " " ;
608 cout << "y=" << point[1]/cm << " ";
609 cout << "z=" << point[2]/cm << " ";
610 cout << "r=" << TC/cm << " ";
611 cout << "z=" << LC/cm << " ";
612 cout << "phi=" << phi*180/3.141592 << " ";
613 cout << "IT=" << IT << " ";
614 cout << "IL=" << IL << " ";
615 cout << "Bx=" << psfield[0]/gauss << " ";
616 cout << "By=" << psfield[1]/gauss << " ";
617 cout << "Bz=" << psfield[2]/gauss << endl;
618 }
619 }
620 for(int i=0; i<3; i++) Field[i].push_back(psfield[i]);
621 }
622
623
624 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
625 // phi-segmented field in cylindrical coordinates
626 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
627 if(B3DCylX.size() && B3DCylY.size() && B3DCylZ.size())
628 {
629 double mfield[3] = {0,0,0};
630 double rotpsfield[3] = {0,0,0};
631
632 double tC, pC, lC;
633 double pLC;
634 double Bx, By, Bz;
635 unsigned int Ip, It, Il;
636
637 pC = atan2( Point[1], Point[0] )*rad;
638 if( pC < 0 ) pC += 360*deg;
639
640 tC = sqrt(Point[0]*Point[0] + Point[1]*Point[1]);
641 lC = Point[2];
642
643 // Rotating the point to within the map limit
644 int segment = 0;
645 pLC = pC;
646 while (pLC/deg > 30)
647 {
648 pLC -= 60*deg;
649 segment++;
650 }
651
652 double dphi = pC - pLC;
653 int sign = (pLC >= 0 ? 1 : -1);
654 double apLC = fabs(pLC);
655
656 Ip = (unsigned int) floor( ( apLC/deg - table_start[0]/deg ) / (cell_size[0]/deg ) ) ;
657 It = (unsigned int) floor( ( tC/mm - table_start[1]/mm ) / (cell_size[1]/mm ) ) ;
658 Il = (unsigned int) floor( ( lC/mm - table_start[2]/mm ) / (cell_size[2]/mm ) ) ;
659
660 if( fabs( table_start[0]/mm + Ip*cell_size[0]/deg - apLC) > fabs( table_start[0]/mm + (Ip+1)*cell_size[0]/mm - apLC) ) Ip++;
661 if( fabs( table_start[1]/mm + It*cell_size[1]/mm - tC) > fabs( table_start[1]/mm + (It+1)*cell_size[1]/mm - tC) ) It++;
662 if( fabs( table_start[2]/mm + Il*cell_size[2]/mm - lC) > fabs( table_start[2]/mm + (Il+1)*cell_size[2]/mm - lC) ) Il++;
663
664 // Getting Field at the rotated point
665 // vector sizes are checked on all components
666 // (even if only one is enough)
667 if( Ip < B3DCylX.size() && Ip < B3DCylY.size() && Ip < B3DCylZ.size())
668 if( It < B3DCylX[Ip].size() && It < B3DCylY[Ip].size() && It < B3DCylZ[Ip].size())
669 if(Il < B3DCylX[Ip][It].size() && Il < B3DCylY[Ip][It].size() && Il < B3DCylZ[Ip][It].size())
670 {
671 // Field at local point
672 mfield[0] = B3DCylX[Ip][It][Il];
673 mfield[1] = B3DCylY[Ip][It][Il];
674 mfield[2] = B3DCylZ[Ip][It][Il];
675
676
677 // Rotating the field back to original point
678 rotpsfield[0] = sign*mfield[0] * cos(dphi/rad) - mfield[1] * sin(dphi/rad);
679 rotpsfield[1] = +sign*mfield[0] * sin(dphi/rad) + mfield[1] * cos(dphi/rad);
680 rotpsfield[2] = sign*mfield[2];
681
682 if(MGN_VERBOSITY>6)
683 {
684 cout << hd_msg << " Phi-Segmented Field: Cart. and Cyl. coord. (cm), indexes, local and rotated field values (gauss):" << endl;
685 cout << " x=" << point[0]/cm << " " ;
686 cout << "y=" << point[1]/cm << " ";
687 cout << "z=" << point[2]/cm << " ";
688 cout << "phi=" << pC/deg << " ";
689 cout << "r=" << tC/cm << " ";
690 cout << "z=" << lC/cm << " ";
691 cout << "dphi=" << dphi/deg << " ";
692 cout << "dphir=" << dphi/rad << " ";
693 cout << "lphi=" << (sign == 1 ? "+ " : "- ") << pLC/deg << " ";
694 cout << "segment=" << segment << " ";
695 cout << "Ip=" << Ip << " ";
696 cout << "It=" << It << " ";
697 cout << "Il=" << Il << " ";
698 cout << "lBx=" << mfield[0]/gauss << " ";
699 cout << "lBy=" << mfield[1]/gauss << " ";
700 cout << "lBz=" << mfield[2]/gauss << " " ;
701 cout << "rBx=" << rotpsfield[0]/gauss << " ";
702 cout << "rBy=" << rotpsfield[1]/gauss << " ";
703 cout << "rBz=" << rotpsfield[2]/gauss << endl;
704 }
705 }
706 for(int i=0; i<3; i++) Field[i].push_back(-rotpsfield[i]);
707 }
708
709
710 // %%%%%%%%%%%%%%%%%%
711 // Summing the Fields
712 // %%%%%%%%%%%%%%%%%%
713 for(int i=0; i<Field[0].size(); i++)
714 for(int j=0; j<3; j++)
715 Bfield[j] += Field[j][i];
716
717 if(MGN_VERBOSITY>5)
718 {
719 cout << hd_msg << " Total Field: coordinates (cm), magnetic field values (gauss):" << endl ;
720 cout << " x=" << point[0]/cm << " " ;
721 cout << "y=" << point[1]/cm << " ";
722 cout << "z=" << point[2]/cm << " ";
723 cout << "Bx=" << Bfield[0]/gauss << " ";
724 cout << "By=" << Bfield[1]/gauss << " ";
725 cout << "Bz=" << Bfield[2]/gauss << endl << endl;
726 }
727
728}
729
730
731
732
733
734
735
736
737
738
739
740
741
Note: See TracBrowser for help on using the repository browser.