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" 35 string hd_msg = Opt.
args[
"LOG_MSG"].args +
" Magnetic Field >> " ;
36 double MGN_VERBOSITY = Opt.
args[
"MGN_VERBOSITY"].arg;
37 string database = Opt.
args[
"DATABASE"].args;
38 string dbtable =
"magnetic_fields";
39 string dbhost = Opt.
args[
"DBHOST"].args;
41 string dbUser = Opt.
args[
"DBUSER"].args;
42 string dbPswd = Opt.
args[
"DBPSWD"].args;
44 vector<opts> FIELD_SCALES = Opt.
get_args(
"SCALE_FIELD");
45 map<string, double> SCALES;
46 for(
unsigned int f=0; f<FIELD_SCALES.size(); f++)
48 string SCALEF = FIELD_SCALES[f].args;
50 int ppos = SCALEF.find(
",");
51 fieldname.assign(SCALEF, 0, ppos);
52 SCALEF.assign(SCALEF, ppos+1, SCALEF.size());
53 SCALES[fieldname] = atof(SCALEF.c_str());
56 map<string, MagneticField> FieldMap;
58 QSqlDatabase db = QSqlDatabase::addDatabase(
"QMYSQL");
59 db.setHostName(dbhost.c_str());
60 db.setDatabaseName(database.c_str());
61 db.setUserName( dbUser.c_str() );
62 db.setPassword( dbPswd.c_str() );
68 cout << hd_msg <<
" Database not connected. Exiting." << endl;
74 string dbexecute =
"select name, type, magnitude, swim_method, description from " + dbtable ;
75 q.exec(dbexecute.c_str());
78 cout << hd_msg <<
" Available Magnetic Fields: " << endl << endl;
94 if(SCALES.find(magneticField.
name) != SCALES.end())
97 cout << hd_msg <<
" SCALE FACTOR: Magnetic Field " << magneticField.
name <<
" scaled by: " << magneticField.
scale_factor << endl;
101 FieldMap[magneticField.
name] = magneticField;
107 cout << magneticField.
name <<
" | ";
111 cout << magneticField.
name <<
" | type: | ";
112 cout << magneticField.
type << endl;
115 cout << magneticField.
name <<
" | Magnitude: | ";
119 cout << magneticField.
name <<
" | Swim Method: | ";
121 cout <<
" -------------------------------------------------------------- " << endl;
128 db.removeDatabase(
"qt_sql_default_connection");
136 string hd_msg =
gemcOpt.
args[
"LOG_MSG"].args +
" Magnetic Field: >> ";
137 double MGN_VERBOSITY =
gemcOpt.
args[
"MGN_VERBOSITY"].arg;
141 string var, format, symmetry, MapFile;
142 string var1, var2, var3, dim;
143 string dimSpc, dimFld;
145 string integration_method;
148 vars >> var >> format >> symmetry >> MapFile;
165 cout << hd_msg <<
" <" <<
name <<
"> is a uniform magnetic field type, scaled by " <<
scale_factor << endl;
166 cout << hd_msg <<
" <" <<
name <<
"> dimensions:" ;
167 cout <<
" (" << x/gauss <<
", " << y/gauss <<
", " << z/gauss <<
") gauss." << endl;
169 G4UniformMagField* magField =
new G4UniformMagField(G4ThreeVector((x/gauss)*gauss, (y/gauss)*gauss, (z/gauss)*gauss));
171 G4Mag_UsualEqRhs* iEquation =
new G4Mag_UsualEqRhs(magField);
172 G4MagIntegratorStepper* iStepper =
new G4ClassicalRK4(iEquation);
173 G4ChordFinder* iChordFinder =
new G4ChordFinder(magField, 1.0e-2*mm, iStepper);
175 MFM =
new G4FieldManager(magField, iChordFinder);
188 if(var ==
"mapped" && symmetry ==
"Dipole-y")
192 int TNPOINTS, LNPOINTS;
193 double tlimits[2], llimits[2];
199 vars >> var1 >> var2 >> dim;
202 units[0].assign(dim);
206 vars >> var1 >> var2 >> dim;
209 units[1].assign(dim);
213 vars >> var1 >> var2 >> var3 >> dimSpc >> dimFld;
214 mapOrigin[0] =
get_number(var1 +
"*" + dimSpc);
215 mapOrigin[1] =
get_number(var2 +
"*" + dimSpc);
216 mapOrigin[2] =
get_number(var3 +
"*" + dimSpc);
217 units[3].assign( dimSpc );
218 units[4].assign( dimFld);
222 vars >> integration_method;
225 vars >> integration_method;
228 cout << hd_msg <<
" <" <<
name <<
"> is a " << symmetry <<
" mapped field in cartesian coordinates" << endl;;
229 cout << hd_msg <<
" <" <<
name <<
"> has (" << TNPOINTS <<
", " << LNPOINTS <<
") points." << endl;;
230 cout << hd_msg <<
" Tranverse Boundaries: (" << tlimits[0]/cm <<
", " << tlimits[1]/cm <<
") cm." << endl;
231 cout << hd_msg <<
" Longitudinal Boundaries: (" << llimits[0]/cm <<
", " << llimits[1]/cm <<
") cm." << endl;
232 cout << hd_msg <<
" Map Displacement: (" << mapOrigin[0]/cm <<
", " 233 << mapOrigin[1]/cm <<
", " 234 << mapOrigin[2]/cm <<
") cm." << endl;
235 cout << hd_msg <<
" Integration Method: " << integration_method << endl;
236 cout << hd_msg <<
" Map Field Units: " << units[4] << endl;
237 cout << hd_msg <<
" Map File: " << MapFile << endl;
249 if(var ==
"mapped" && (symmetry ==
"cylindrical" || symmetry ==
"cylindrical-x" || symmetry ==
"cylindrical-y"))
253 int TNPOINTS, LNPOINTS;
254 double tlimits[2], llimits[2];
260 vars >> var1 >> var2 >> dim;
263 units[0].assign(dim);
268 vars >> var1 >> var2 >> dim;
271 units[1].assign(dim);
274 vars >> var1 >> var2 >> var3 >> dimSpc >> dimFld;
275 mapOrigin[0] =
get_number(var1 +
"*" + dimSpc);
276 mapOrigin[1] =
get_number(var2 +
"*" + dimSpc);
277 mapOrigin[2] =
get_number(var3 +
"*" + dimSpc);
278 units[3].assign( dimSpc );
279 units[4].assign( dimFld);
283 vars >> integration_method;
286 vars >> integration_method;
289 cout << hd_msg <<
" <" <<
name <<
"> is a phi-symmetric mapped field in cylindrical coordinates" << endl;;
290 cout << hd_msg <<
" <" <<
name <<
"> has (" << TNPOINTS <<
", " << LNPOINTS <<
") points." << endl;;
291 cout << hd_msg <<
" Tranverse Boundaries: (" << tlimits[0]/cm <<
", " << tlimits[1]/cm <<
") cm." << endl;
292 cout << hd_msg <<
" Longitudinal Boundaries: (" << llimits[0]/cm <<
", " << llimits[1]/cm <<
") cm." << endl;
293 cout << hd_msg <<
" Map Displacement: (" << mapOrigin[0]/cm <<
", " 294 << mapOrigin[1]/cm <<
", " 295 << mapOrigin[2]/cm <<
") cm." << endl;
296 cout << hd_msg <<
" Integration Method: " << integration_method << endl;
297 cout << hd_msg <<
" Map Field Units: " << units[4] << endl;
298 cout << hd_msg <<
" Map File: " << MapFile << endl;
301 mappedfield =
new MappedField(
gemcOpt, TNPOINTS, LNPOINTS, tlimits, llimits, MapFile, mapOrigin, units,
scale_factor, symmetry, 0);
311 if(var ==
"mapped" && symmetry ==
"phi-segmented")
315 int TNPOINTS, PNPOINTS, LNPOINTS;
316 double plimits[2], tlimits[2], llimits[2];
322 vars >> var1 >> var2 >> dim;
325 units[0].assign(dim);
329 vars >> var1 >> var2 >> dim;
332 units[1].assign(dim);
336 vars >> var1 >> var2 >> dim;
339 units[2].assign(dim);
342 vars >> var1 >> var2 >> var3 >> dimSpc >> dimFld;
343 mapOrigin[0] =
get_number(var1 +
"*" + dimSpc);
344 mapOrigin[1] =
get_number(var2 +
"*" + dimSpc);
345 mapOrigin[2] =
get_number(var3 +
"*" + dimSpc);
346 units[3].assign( dimSpc );
347 units[4].assign( dimFld);
351 vars >> integration_method;
354 vars >> integration_method;
355 double segm_phi_span = 2*(plimits[1] - plimits[0]);
356 int nsegments = (int) (360.0/(segm_phi_span/deg));
357 if( fabs( segm_phi_span*nsegments/deg - 360 ) > 1.0e-2 )
359 cout << hd_msg <<
" <" <<
name <<
"> segmentation is wrong: " << nsegments <<
" segments, each span " 360 << segm_phi_span/deg <<
": it doesn't add to 360, but " << segm_phi_span*nsegments/deg <<
" Exiting." << endl;
366 cout << hd_msg <<
" <" <<
name <<
"> is a phi-segmented mapped field in cylindrical coordinates" << endl;;
367 cout << hd_msg <<
" <" <<
name <<
"> has (" << PNPOINTS <<
", " << TNPOINTS <<
", " << LNPOINTS <<
") points" << endl;;
368 cout << hd_msg <<
" Azimuthal Boundaries: (" << plimits[0]/deg <<
", " << plimits[1]/deg <<
") deg" << endl;
369 cout << hd_msg <<
" Tranverse Boundaries: (" << tlimits[0]/cm <<
", " << tlimits[1]/cm <<
") cm" << endl;
370 cout << hd_msg <<
" Longitudinal Boundaries: (" << llimits[0]/cm <<
", " << llimits[1]/cm <<
") cm" << endl;
371 cout << hd_msg <<
" Phi segment span, number of segments: " << segm_phi_span/deg <<
" deg, " << nsegments << endl;
372 cout << hd_msg <<
" Map Displacement: (" << mapOrigin[0]/cm <<
", " 373 << mapOrigin[1]/cm <<
", " 374 << mapOrigin[2]/cm <<
") cm" << endl;
375 cout << hd_msg <<
" Integration Method: " << integration_method << endl;
376 cout << hd_msg <<
" Map Field Units: " << units[4] << endl;
377 cout << hd_msg <<
" Map File: " << MapFile << endl;
379 mappedfield =
new MappedField(
gemcOpt, TNPOINTS, PNPOINTS, LNPOINTS, tlimits, plimits, llimits, MapFile, mapOrigin, units,
scale_factor);
390 if(var ==
"mapped" && symmetry ==
"y-symmetric")
394 int XNPOINTS, YNPOINTS, ZNPOINTS;
395 double xlimits[2], ylimits[2], zlimits[2];
401 vars >> var1 >> var2 >> dim;
404 units[0].assign(dim);
408 vars >> var1 >> var2 >> dim;
411 units[1].assign(dim);
415 vars >> var1 >> var2 >> dim;
418 units[2].assign(dim);
421 vars >> var1 >> var2 >> var3 >> dimSpc >> dimFld;
422 mapOrigin[0] =
get_number(var1 +
"*" + dimSpc);
423 mapOrigin[1] =
get_number(var2 +
"*" + dimSpc);
424 mapOrigin[2] =
get_number(var3 +
"*" + dimSpc);
425 units[3].assign( dimSpc );
426 units[4].assign( dimFld);
430 vars >> integration_method;
433 vars >> integration_method;
437 cout << hd_msg <<
" <" <<
name <<
"> is a cartesian y-symmetric mapped field in cartesian coordinates" << endl;;
438 cout << hd_msg <<
" <" <<
name <<
"> has (" << XNPOINTS <<
", " << YNPOINTS <<
", " << ZNPOINTS <<
") points" << endl;;
439 cout << hd_msg <<
" X Boundaries: (" << xlimits[0]/cm <<
", " << xlimits[1]/cm <<
") cm" << endl;
440 cout << hd_msg <<
" Y Boundaries: (" << ylimits[0]/cm <<
", " << ylimits[1]/cm <<
") cm" << endl;
441 cout << hd_msg <<
" Z Boundaries: (" << zlimits[0]/cm <<
", " << zlimits[1]/cm <<
") cm" << endl;
442 cout << hd_msg <<
" Map Displacement: (" 443 << mapOrigin[0]/cm <<
", " << mapOrigin[1]/cm <<
", " << mapOrigin[2]/cm <<
") cm" << endl;
444 cout << hd_msg <<
" Integration Method: " << integration_method << endl;
445 cout << hd_msg <<
" Map Field Units: `" << units[4] <<
"`" << endl;
446 cout << hd_msg <<
" Map File: `" << MapFile <<
"`" << endl;
454 if(integration_method ==
"RungeKutta")
458 G4Mag_UsualEqRhs* iEquation =
new G4Mag_UsualEqRhs(
mappedfield);
459 G4MagIntegratorStepper* iStepper =
new G4HelixSimpleRunge(iEquation);
460 G4ChordFinder* iChordFinder =
new G4ChordFinder(
mappedfield, 1.0e-2*mm, iStepper);
462 MFM =
new G4FieldManager(
mappedfield, iChordFinder);
463 MFM->SetDeltaOneStep(1*mm);
464 MFM->SetDeltaIntersection(1*mm);
475 string filename,
double origin[3],
string units[5],
double scale_factor,
string symmetry)
479 string hd_msg =
gemcOpt.
args[
"LOG_MSG"].args +
" Magnetic Field Constructor: >> ";
480 MGN_VERBOSITY = (int)
gemcOpt.
args[
"MGN_VERBOSITY"].arg ;
481 string field_dir =
gemcOpt.
args[
"FIELD_DIR"].args ;
482 if( getenv(
"JLAB_ROOT") == NULL){
483 cout << hd_msg <<
" ERROR: Please set JLAB_ROOT to point to the directory containing noarch/data \n";
486 string field_file = (string) getenv(
"JLAB_ROOT") +
"/noarch/data/" + filename;
488 if(field_dir !=
"env")
489 field_file = field_dir +
"/" + filename;
491 mapOrigin[0] = origin[0];
492 mapOrigin[1] = origin[1];
493 mapOrigin[2] = origin[2];
495 table_start[0] = tlimits[0];
496 table_start[1] = llimits[0];
497 cell_size[0] = (tlimits[1] - tlimits[0])/( TNPOINTS - 1);
498 cell_size[1] = (llimits[1] - llimits[0])/( LNPOINTS - 1);
502 cout << hd_msg <<
" The Transverse cell size is: " << cell_size[0]/cm <<
" cm" << endl
503 << hd_msg <<
" and the Longitudinal cell size is: " << cell_size[1]/cm <<
" cm" << endl;
507 ifstream IN(field_file.c_str());
510 cout << hd_msg <<
" File " << field_file <<
" could not be opened. Exiting." << endl;
513 cout << hd_msg <<
" Reading map file: " << field_file <<
"... ";
518 BDipole.resize( LNPOINTS );
519 for(
int il=0; il<LNPOINTS; il++)
521 BDipole[il].resize(TNPOINTS);
531 for(
int il=0; il<LNPOINTS; il++)
533 for(
int it=0; it<TNPOINTS; it++)
536 if(units[0] ==
"cm") LC *= cm;
537 else if(units[0] ==
"m") LC *= m;
538 else if(units[0] ==
"mm") LC *= mm;
539 else cout << hd_msg <<
" Dimension Unit " << units[1] <<
" not implemented yet." << endl;
540 if(units[1] ==
"cm") TC *= cm;
541 else if(units[1] ==
"m") TC *= m;
542 else if(units[1] ==
"mm") TC *= mm;
543 else cout << hd_msg <<
" Dimension Unit " << units[0] <<
" not implemented yet." << endl;
546 if( (tlimits[0] + it*cell_size[0] - TC)/TC > 0.001)
548 cout << hd_msg << it <<
" transverse index wrong. Map point should be " << tlimits[0] + it*cell_size[0]
549 <<
" but it's " << TC <<
" instead." << endl;
552 IT = (
unsigned int) floor( ( TC/mm - table_start[0]/mm + cell_size[0]/mm/2 ) / ( cell_size[0]/mm ) ) ;
553 IL = (
unsigned int) floor( ( LC/mm - table_start[1]/mm + cell_size[1]/mm/2 ) / ( cell_size[1]/mm ) ) ;
557 if(units[4] ==
"gauss")
559 BDipole[IL][IT] = B*gauss;
561 else if(units[4] ==
"kilogauss")
563 BDipole[IL][IT] = B*kilogauss;
565 else if(units[4] ==
"T")
567 BDipole[IL][IT] = B*tesla;
571 cout << hd_msg <<
" Field Unit " << units[4] <<
" not implemented yet." << endl;
575 if( (llimits[0] + il*cell_size[1] - LC)/LC > 0.001)
577 cout << hd_msg << il <<
" longitudinal index wrong. Map point should be " << llimits[0] + il*cell_size[1]
578 <<
" but it's " << LC <<
" instead." << endl;
583 cout <<
" done!" << endl;
592 string filename,
double origin[3],
string units[5],
double scale_factor,
string symmetry,
int dummy)
595 string hd_msg =
gemcOpt.
args[
"LOG_MSG"].args +
" Magnetic Field Constructor: >> ";
596 MGN_VERBOSITY = (int)
gemcOpt.
args[
"MGN_VERBOSITY"].arg ;
597 string field_dir =
gemcOpt.
args[
"FIELD_DIR"].args ;
598 if( getenv(
"JLAB_ROOT") == NULL){
599 cout << hd_msg <<
" ERROR: Please set JLAB_ROOT to point to the directory containing noarch/data \n";
602 string field_file = (string) getenv(
"JLAB_ROOT") +
"/noarch/data/" + filename;
605 if(field_dir !=
"env")
606 field_file = field_dir +
"/" + filename;
609 mapOrigin[0] = origin[0];
610 mapOrigin[1] = origin[1];
611 mapOrigin[2] = origin[2];
613 table_start[0] = tlimits[0];
614 table_start[1] = llimits[0];
615 cell_size[0] = (tlimits[1] - tlimits[0])/( TNPOINTS - 1);
616 cell_size[1] = (llimits[1] - llimits[0])/( LNPOINTS - 1);
620 cout << hd_msg <<
" The transverse cell size is: " << cell_size[0]/cm <<
" cm" << endl
621 << hd_msg <<
" and the longitudinal cell size is: " << cell_size[1]/cm <<
" cm" << endl;
625 ifstream IN(field_file.c_str());
628 cout << hd_msg <<
" File " << field_file <<
" could not be opened. Exiting." << endl;
631 cout << hd_msg <<
" Reading map file: " << field_file <<
"... ";
636 B2DCylT.resize( TNPOINTS );
637 B2DCylL.resize( TNPOINTS );
638 for(
int it=0; it<TNPOINTS; it++)
640 B2DCylT[it].resize(LNPOINTS);
641 B2DCylL[it].resize(LNPOINTS);
651 for(
int it=0; it<TNPOINTS; it++)
653 for(
int il=0; il<LNPOINTS; il++)
655 IN >> TC >> LC >> BT >> BL;
656 if(units[0] ==
"cm") TC *= cm;
657 else if(units[0] ==
"m") TC *= m;
658 else if(units[0] ==
"mm") TC *= mm;
659 else cout << hd_msg <<
" Dimension Unit " << units[0] <<
" not implemented yet." << endl;
660 if(units[1] ==
"cm") LC *= cm;
661 else if(units[1] ==
"m") LC *= m;
662 else if(units[1] ==
"mm") LC *= mm;
663 else cout << hd_msg <<
" Dimension Unit " << units[1] <<
" not implemented yet." << endl;
666 if( (llimits[0] + il*cell_size[1] - LC)/LC > 0.001)
668 cout << hd_msg << il <<
" longitudinal index wrong. Map point should be " << llimits[0] + il*cell_size[1]
669 <<
" but it's " << LC <<
" instead." << endl;
672 IT = (
unsigned int) floor( ( TC/mm - table_start[0]/mm + cell_size[0]/mm/2 ) / ( cell_size[0]/mm ) ) ;
673 IL = (
unsigned int) floor( ( LC/mm - table_start[1]/mm + cell_size[1]/mm/2 ) / ( cell_size[1]/mm ) ) ;
678 if(units[4] ==
"gauss")
680 B2DCylT[IT][IL] = BT*gauss;
681 B2DCylL[IT][IL] = BL*gauss;
683 else if(units[4] ==
"kilogauss")
685 B2DCylT[IT][IL] = BT*kilogauss;
686 B2DCylL[IT][IL] = BL*kilogauss;
688 else if(units[4] ==
"T")
690 B2DCylT[IT][IL] = BT*tesla;
691 B2DCylL[IT][IL] = BL*tesla;
695 cout << hd_msg <<
" Field Unit " << units[4] <<
" not implemented yet." << endl;
699 if( (tlimits[0] + it*cell_size[0] - TC)/TC > 0.001)
701 cout << hd_msg << it <<
" transverse index wrong. Map point should be " << tlimits[0] + it*cell_size[0]
702 <<
" but it's " << TC <<
" instead." << endl;
707 cout <<
" done!" << endl;
716 string filename,
double origin[3],
string units[5],
double scale_factor)
719 string hd_msg =
gemcOpt.
args[
"LOG_MSG"].args +
" Magnetic Field Constructor: >> ";
720 MGN_VERBOSITY = (int)
gemcOpt.
args[
"MGN_VERBOSITY"].arg ;
721 string field_dir =
gemcOpt.
args[
"FIELD_DIR"].args ;
722 if( getenv(
"JLAB_ROOT") == NULL){
723 cout << hd_msg <<
" ERROR: Please set JLAB_ROOT to point to the directory containing noarch/data \n";
726 string field_file = (string) getenv(
"JLAB_ROOT") +
"/noarch/data/" + filename;
728 if(field_dir !=
"env")
729 field_file = field_dir +
"/" + filename;
731 mapOrigin[0] = origin[0];
732 mapOrigin[1] = origin[1];
733 mapOrigin[2] = origin[2];
735 table_start[0] = plimits[0];
736 table_start[1] = tlimits[0];
737 table_start[2] = llimits[0];
738 cell_size[0] = (plimits[1] - plimits[0])/( pNPOINTS - 1);
739 cell_size[1] = (tlimits[1] - tlimits[0])/( rNPOINTS - 1);
740 cell_size[2] = (llimits[1] - llimits[0])/( zNPOINTS - 1);
744 cout << hd_msg <<
" the phi cell size is: " << cell_size[0]/deg <<
" degrees" << endl
745 << hd_msg <<
" The radius cell size is: " << cell_size[1]/cm <<
" cm" << endl
746 << hd_msg <<
" and the z cell size is: " << cell_size[2]/cm <<
" cm" << endl;
749 ifstream IN(field_file.c_str());
752 cout << hd_msg <<
" File " << field_file <<
" could not be opened. Exiting." << endl;
755 cout << hd_msg <<
" Reading map file: " << field_file <<
"... ";
763 B3DCylX.resize( pNPOINTS );
764 B3DCylY.resize( pNPOINTS );
765 B3DCylZ.resize( pNPOINTS );
766 for(
int ip=0; ip<pNPOINTS; ip++)
768 B3DCylX[ip].resize( rNPOINTS );
769 B3DCylY[ip].resize( rNPOINTS );
770 B3DCylZ[ip].resize( rNPOINTS );
771 for(
int ir=0; ir<rNPOINTS; ir++)
773 B3DCylX[ip][ir].resize( zNPOINTS );
774 B3DCylY[ip][ir].resize( zNPOINTS );
775 B3DCylZ[ip][ir].resize( zNPOINTS );
784 unsigned int It, Ip, Il;
785 for(
int ip=0; ip<pNPOINTS; ip++)
787 for(
int it=0; it<rNPOINTS; it++)
789 for(
int il=0; il<zNPOINTS; il++)
791 IN >> pC >> tC >> lC >> Bx >> By >> Bz;
793 if(units[0] ==
"deg") pC = pC*deg;
794 else cout << hd_msg <<
" Dimension Unit " << units[0] <<
" not implemented yet." << endl;
795 if(units[1] ==
"cm") tC *= cm;
796 else cout << hd_msg <<
" Dimension Unit " << units[1] <<
" not implemented yet." << endl;
797 if(units[2] ==
"cm") lC *= cm;
798 else cout << hd_msg <<
" Dimension Unit " << units[2] <<
" not implemented yet." << endl;
801 if( (llimits[0] + il*cell_size[2] - lC)/lC > 0.001)
803 cout << hd_msg << il <<
" longitudinal index wrong. Map point should be " << llimits[0] + il*cell_size[2]
804 <<
" but it's " << lC <<
" instead." << endl;
807 Ip = (
unsigned int) floor( ( pC/deg - table_start[0]/deg + cell_size[0]/deg/2 ) / ( cell_size[0]/deg ) ) ;
808 It = (
unsigned int) floor( ( tC/mm - table_start[1]/mm + cell_size[1]/mm/2 ) / ( cell_size[1]/mm ) ) ;
809 Il = (
unsigned int) floor( ( lC/mm - table_start[2]/mm + cell_size[2]/mm/2 ) / ( cell_size[2]/mm ) ) ;
815 if(units[4] ==
"gauss")
817 B3DCylX[Ip][It][Il] = Bx*gauss;
818 B3DCylY[Ip][It][Il] = By*gauss;
819 B3DCylZ[Ip][It][Il] = Bz*gauss;
821 else if(units[4] ==
"kilogauss")
823 B3DCylX[Ip][It][Il] = Bx*kilogauss;
824 B3DCylY[Ip][It][Il] = By*kilogauss;
825 B3DCylZ[Ip][It][Il] = Bz*kilogauss;
827 else if(units[4] ==
"T")
829 B3DCylX[Ip][It][Il] = Bx*tesla;
830 B3DCylY[Ip][It][Il] = By*tesla;
831 B3DCylZ[Ip][It][Il] = Bz*tesla;
836 cout << hd_msg <<
" Field Unit " << units[4] <<
" not implemented yet." << endl;
839 if(MGN_VERBOSITY>10 && MGN_VERBOSITY < 50)
841 cout <<
" phi=" << pC/deg <<
", ip=" << Ip <<
" " 842 <<
" r=" << tC/cm <<
", it=" << It <<
" " 843 <<
" z=" << lC/cm <<
", iz=" << Il <<
" " 844 <<
" Bx=" << B3DCylX[Ip][It][Il]/kilogauss <<
" " 845 <<
" By=" << B3DCylY[Ip][It][Il]/kilogauss <<
" " 846 <<
" Bz=" << B3DCylZ[Ip][It][Il]/kilogauss <<
" kilogauss. Map Values: " 847 <<
" rBx=" << Bx <<
" " 848 <<
" rBy=" << By <<
" " 849 <<
" rBz=" << Bz << endl;
856 if( (tlimits[0] + it*cell_size[1] - tC)/tC > 0.001)
858 cout << hd_msg << it <<
" transverse index wrong. Map point should be " << tlimits[0] + it*cell_size[0]
859 <<
" but it's " << tC <<
" instead." << endl;
865 if( (plimits[0] + ip*cell_size[0] - pC)/pC > 0.001)
867 cout << hd_msg << ip <<
" azimuthal index wrong. Map point should be " << plimits[0] + ip*cell_size[1]
868 <<
" but it's " << pC <<
" instead." << endl;
874 cout <<
" done!" << endl;
882 double ylimits[2],
double xlimits[2],
double zlimits[2],
883 string filename,
double origin[3],
string units[5],
double scale_factor,
bool ySymmetry)
886 string hd_msg =
gemcOpt.
args[
"LOG_MSG"].args +
" Magnetic Field Constructor: >> ";
887 MGN_VERBOSITY = (int)
gemcOpt.
args[
"MGN_VERBOSITY"].arg ;
888 string field_dir =
gemcOpt.
args[
"FIELD_DIR"].args ;
889 if( getenv(
"JLAB_ROOT") == NULL){
890 cout << hd_msg <<
" ERROR: Please set JLAB_ROOT to point to the directory containing noarch/data \n";
893 string field_file = (string) getenv(
"JLAB_ROOT") +
"/noarch/data/" + filename;
895 if(field_dir !=
"env")
896 field_file = field_dir +
"/" + filename;
900 if( ySymmetry ) nsegments = 2;
902 mapOrigin[0] = origin[0];
903 mapOrigin[1] = origin[1];
904 mapOrigin[2] = origin[2];
906 table_start[0] = xlimits[0];
907 table_start[1] = ylimits[0];
908 table_start[2] = zlimits[0];
910 table_end[0] = xlimits[1];
911 table_end[1] = ylimits[1];
912 table_end[2] = zlimits[1];
916 table_start[1] = fabs( table_start[1] );
917 table_end[1] = fabs( table_end[1] );
920 cell_size[0] = (table_end[0] - table_start[0])/( xNPOINTS - 1);
921 cell_size[1] = (table_end[1] - table_start[1])/( yNPOINTS - 1);
922 cell_size[2] = (table_end[2] - table_start[2])/( zNPOINTS - 1);
927 cout << hd_msg <<
" the X cell size is: " << cell_size[0]/cm <<
" cm" << endl
928 << hd_msg <<
" The Y cell size is: " << cell_size[1]/cm <<
" cm" << endl
929 << hd_msg <<
" and the Z cell size is: " << cell_size[2]/cm <<
" cm" << endl;
932 ifstream IN(field_file.c_str());
935 cout << hd_msg <<
" File " << field_file <<
" could not be opened. Exiting." << endl;
938 cout << hd_msg <<
" Reading map file: " << field_file <<
"... ";
946 B3DCartX.resize( xNPOINTS );
947 B3DCartY.resize( xNPOINTS );
948 B3DCartZ.resize( xNPOINTS );
949 for(
int ix=0; ix<xNPOINTS; ix++)
951 B3DCartX[ix].resize( yNPOINTS );
952 B3DCartY[ix].resize( yNPOINTS );
953 B3DCartZ[ix].resize( yNPOINTS );
954 for(
int iy=0; iy<yNPOINTS; iy++)
956 B3DCartX[ix][iy].resize( zNPOINTS );
957 B3DCartY[ix][iy].resize( zNPOINTS );
958 B3DCartZ[ix][iy].resize( zNPOINTS );
967 unsigned int Ix, Iy, Iz;
968 for(
int ix=0; ix<xNPOINTS; ix++)
970 for(
int iz=0; iz<zNPOINTS; iz++)
972 for(
int iy=0; iy<yNPOINTS; iy++)
974 IN >> xC >> yC >> zC >> Bx >> By >> Bz;
975 if( ySymmetry ) yC = fabs( yC );
977 if(units[0] ==
"cm") xC *= cm;
978 else if(units[0] ==
"m") xC *= m;
979 else if(units[0] ==
"mm") xC *= mm;
980 else cout << hd_msg <<
" Dimension Unit " << units[0] <<
" not implemented yet." << endl;
981 if(units[1] ==
"cm") yC *= cm;
982 else if(units[1] ==
"m") yC *= m;
983 else if(units[1] ==
"mm") yC *= mm;
984 else cout << hd_msg <<
" Dimension Unit " << units[1] <<
" not implemented yet." << endl;
985 if(units[2] ==
"cm") zC *= cm;
986 else if(units[2] ==
"m") zC *= m;
987 else if(units[2] ==
"mm") zC *= mm;
988 else cout << hd_msg <<
" Dimension Unit " << units[2] <<
" not implemented yet." << endl;
991 if( (table_start[1] + iy*cell_size[1] - yC)/yC > 0.001)
993 cout << hd_msg << iy <<
" Y index wrong. Map point should be " << table_start[1] + iy*cell_size[1]
994 <<
" but it's " << yC <<
" instead." << endl;
997 Ix = (
unsigned int) floor( ( xC/mm - table_start[0]/mm + cell_size[0]/mm/2 ) / ( cell_size[0]/mm ) ) ;
998 Iy = (
unsigned int) floor( ( yC/mm - table_start[1]/mm + cell_size[1]/mm/2 ) / ( cell_size[1]/mm ) ) ;
999 Iz = (
unsigned int) floor( ( zC/mm - table_start[2]/mm + cell_size[2]/mm/2 ) / ( cell_size[2]/mm ) ) ;
1004 if(units[4] ==
"gauss")
1006 B3DCartX[Ix][Iy][Iz] = Bx*gauss;
1007 B3DCartY[Ix][Iy][Iz] = By*gauss;
1008 B3DCartZ[Ix][Iy][Iz] = Bz*gauss;
1009 }
else if(units[4] ==
"kilogauss")
1011 B3DCartX[Ix][Iy][Iz] = Bx*kilogauss;
1012 B3DCartY[Ix][Iy][Iz] = By*kilogauss;
1013 B3DCartZ[Ix][Iy][Iz] = Bz*kilogauss;
1014 }
else if(units[4] ==
"T")
1016 B3DCartX[Ix][Iy][Iz] = Bx*tesla;
1017 B3DCartY[Ix][Iy][Iz] = By*tesla;
1018 B3DCartZ[Ix][Iy][Iz] = Bz*tesla;
1022 cout << hd_msg <<
" Field Unit " << units[4] <<
" not implemented yet." << endl;
1025 if(MGN_VERBOSITY>10 && MGN_VERBOSITY < 50)
1027 cout <<
" x=" << xC/cm <<
", ix=" << Ix <<
" " 1028 <<
" y=" << yC/cm <<
", iy=" << Iy <<
" " 1029 <<
" z=" << zC/cm <<
", iz=" << Iz <<
" " 1030 <<
" Bx=" << B3DCartX[Ix][Iy][Iz]/kilogauss <<
" " 1031 <<
" By=" << B3DCartY[Ix][Iy][Iz]/kilogauss <<
" " 1032 <<
" Bz=" << B3DCartZ[Ix][Iy][Iz]/kilogauss <<
" kilogauss. Map Values: " 1033 <<
" rBx=" << Bx <<
" " 1034 <<
" rBy=" << By <<
" " 1035 <<
" rBz=" << Bz << endl;
1040 if( (table_start[2] + iz*cell_size[2] - zC)/zC > 0.001)
1042 cout << hd_msg << iz <<
" Z index wrong. Map point should be " << table_start[2] + iz*cell_size[2]
1043 <<
" but it's " << zC <<
" instead." << endl;
1049 if( (table_start[0] + ix*cell_size[0] - xC)/xC > 0.001)
1051 cout << hd_msg << ix <<
" X index wrong. Map point should be " << table_start[0] + ix*cell_size[0]
1052 <<
" but it's " << xC <<
" instead." << endl;
1057 cout <<
" done!" << endl;
1071 vector<double> Field[3];
1072 static int FIRST_ONLY;
1074 Point[0] = point[0] - mapOrigin[0]/mm;
1075 Point[1] = point[1] - mapOrigin[1]/mm;
1076 Point[2] = point[2] - mapOrigin[2]/mm;
1078 Bfield[0] = Bfield[1] = Bfield[2] = 0*gauss;
1085 double psfield[3] = {0,0,0};
1086 unsigned int IT, IL;
1090 if(Symmetry ==
"Dipole-x")
1095 if(Symmetry ==
"Dipole-y")
1100 if(Symmetry ==
"Dipole-z")
1107 IT = (
unsigned int) floor( ( TC - table_start[0]/mm ) / (cell_size[0]/mm) ) ;
1108 IL = (
unsigned int) floor( ( LC - table_start[1]/mm ) / (cell_size[1]/mm) ) ;
1110 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++;
1111 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++;
1114 if(IL < BDipole.size())
1115 if(IT < BDipole[IL].size())
1117 if(Symmetry ==
"Dipole-x") psfield[0] = BDipole[IL][IT];
1118 if(Symmetry ==
"Dipole-y") psfield[1] = BDipole[IL][IT];
1119 if(Symmetry ==
"Dipole-z") psfield[2] = BDipole[IL][IT];
1120 if(MGN_VERBOSITY>5 && FIRST_ONLY != 99)
1122 cout << hd_msg <<
" Dipole Field: Cart. coordinates (cm), table indexes, magnetic field values (gauss):" << endl;
1123 cout <<
" x=" << point[0]/cm <<
" " ;
1124 cout <<
"y=" << point[1]/cm <<
" ";
1125 cout <<
"z=" << point[2]/cm <<
" ";
1126 cout <<
"IT=" << IT <<
" ";
1127 cout <<
"IL=" << IL <<
" ";
1128 cout <<
"Bx=" << psfield[0]/gauss <<
" ";
1129 cout <<
"By=" << psfield[1]/gauss <<
" ";
1130 cout <<
"Bz=" << psfield[2]/gauss << endl;
1133 for(
int i=0; i<3; i++) Field[i].push_back(psfield[i]);
1140 if(B2DCylT.size() && B2DCylL.size())
1142 double psfield[3] = {0,0,0};
1143 unsigned int IT, IL;
1147 TC = sqrt(Point[0]*Point[0] + Point[1]*Point[1]);
1148 G4ThreeVector vpos(Point[0], Point[1], Point[2]);
1152 IT = (
unsigned int) floor( ( TC - table_start[0]/mm ) / (cell_size[0]/mm) ) ;
1153 IL = (
unsigned int) floor( ( LC - table_start[1]/mm ) / (cell_size[1]/mm) ) ;
1155 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++;
1156 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++;
1161 if(IT < B2DCylT.size() && IT < B2DCylL.size())
1162 if(IL < B2DCylT[IT].size() && IL < B2DCylL[IT].size() )
1166 psfield[0] = B2DCylT[IT][IL] * cos(phi);
1167 psfield[1] = B2DCylT[IT][IL] * sin(phi);
1168 psfield[2] = B2DCylL[IT][IL];
1171 if(Symmetry ==
"cylindrical-x")
1173 psfield[2] = B2DCylT[IT][IL] * cos(phi);
1174 psfield[1] = B2DCylT[IT][IL] * sin(phi);
1175 psfield[0] = B2DCylL[IT][IL];
1178 if(Symmetry ==
"cylindrical-y")
1180 psfield[0] = B2DCylT[IT][IL] * cos(phi);
1181 psfield[2] = B2DCylT[IT][IL] * sin(phi);
1182 psfield[1] = B2DCylL[IT][IL];
1185 if(MGN_VERBOSITY>5 && FIRST_ONLY != 99)
1187 cout << hd_msg <<
" Phi-Simmetric Field: Cart. and Cyl. coordinates (cm), table indexes, magnetic field values (gauss):" << endl;
1188 cout <<
" x=" << point[0]/cm <<
" " ;
1189 cout <<
"y=" << point[1]/cm <<
" ";
1190 cout <<
"z=" << point[2]/cm <<
" ";
1191 cout <<
"r=" << TC/cm <<
" ";
1192 cout <<
"z=" << LC/cm <<
" ";
1193 cout <<
"phi=" << phi/deg <<
" ";
1194 cout <<
"IT=" << IT <<
" ";
1195 cout <<
"IL=" << IL <<
" ";
1196 cout <<
"Bx=" << psfield[0]/gauss <<
" ";
1197 cout <<
"By=" << psfield[1]/gauss <<
" ";
1198 cout <<
"Bz=" << psfield[2]/gauss << endl;
1201 for(
int i=0; i<3; i++) Field[i].push_back(psfield[i]);
1208 if(B3DCylX.size() && B3DCylY.size() && B3DCylZ.size())
1210 double mfield[3] = {0,0,0};
1211 double rotpsfield[3] = {0,0,0};
1215 unsigned int Ip, It, Il;
1217 pC = atan2( Point[1], Point[0] )*rad;
1218 if( pC < 0 ) pC += 360*deg;
1220 tC = sqrt(Point[0]*Point[0] + Point[1]*Point[1]);
1226 while (pLC/deg > 30)
1232 double dphi = pC - pLC;
1233 int sign = (pLC >= 0 ? 1 : -1);
1234 double apLC = fabs(pLC);
1236 Ip = (
unsigned int) floor( ( apLC/deg - table_start[0]/deg ) / (cell_size[0]/deg ) ) ;
1237 It = (
unsigned int) floor( ( tC/mm - table_start[1]/mm ) / (cell_size[1]/mm ) ) ;
1238 Il = (
unsigned int) floor( ( lC/mm - table_start[2]/mm ) / (cell_size[2]/mm ) ) ;
1240 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++;
1241 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++;
1242 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++;
1247 if( Ip < B3DCylX.size() && Ip < B3DCylY.size() && Ip < B3DCylZ.size())
1248 if( It < B3DCylX[Ip].size() && It < B3DCylY[Ip].size() && It < B3DCylZ[Ip].size())
1249 if( Il < B3DCylX[Ip][It].size() && Il < B3DCylY[Ip][It].size() && Il < B3DCylZ[Ip][It].size())
1252 mfield[0] = B3DCylX[Ip][It][Il];
1253 mfield[1] = B3DCylY[Ip][It][Il];
1254 mfield[2] = B3DCylZ[Ip][It][Il];
1258 rotpsfield[0] = sign*mfield[0] * cos(dphi/rad) - mfield[1] * sin(dphi/rad);
1259 rotpsfield[1] = +sign*mfield[0] * sin(dphi/rad) + mfield[1] * cos(dphi/rad);
1260 rotpsfield[2] = sign*mfield[2];
1262 if(MGN_VERBOSITY>6 && FIRST_ONLY != 99)
1264 cout << hd_msg <<
" Phi-Segmented Field: Cart. and Cyl. coord. (cm), indexes, local and rotated field values (gauss):" << endl;
1265 cout <<
" x=" << point[0]/cm <<
" " ;
1266 cout <<
"y=" << point[1]/cm <<
" ";
1267 cout <<
"z=" << point[2]/cm <<
" ";
1268 cout <<
"phi=" << pC/deg <<
" ";
1269 cout <<
"r=" << tC/cm <<
" ";
1270 cout <<
"z=" << lC/cm <<
" ";
1271 cout <<
"dphi=" << dphi/deg <<
" ";
1272 cout <<
"dphir=" << dphi/rad <<
" ";
1273 cout <<
"lphi=" << (sign == 1 ?
"+ " :
"- ") << pLC/deg <<
" ";
1274 cout <<
"segment=" << segment <<
" ";
1275 cout <<
"Ip=" << Ip <<
" ";
1276 cout <<
"It=" << It <<
" ";
1277 cout <<
"Il=" << Il <<
" ";
1278 cout <<
"lBx=" << mfield[0]/gauss <<
" ";
1279 cout <<
"lBy=" << mfield[1]/gauss <<
" ";
1280 cout <<
"lBz=" << mfield[2]/gauss <<
" " ;
1281 cout <<
"rBx=" << rotpsfield[0]/gauss <<
" ";
1282 cout <<
"rBy=" << rotpsfield[1]/gauss <<
" ";
1283 cout <<
"rBz=" << rotpsfield[2]/gauss << endl;
1286 for(
int i=0; i<3; i++) Field[i].push_back(-rotpsfield[i]);
1292 if(B3DCartX.size() && B3DCartY.size() && B3DCartZ.size())
1294 double mfield[3] = {0,0,0};
1296 unsigned int Ix, Iy, Iz;
1303 if( nsegments == 2 ) yC = fabs( yC );
1305 Ix = (
unsigned int) floor( ( xC/mm - table_start[0]/mm ) / (cell_size[0]/mm ) ) ;
1306 Iy = (
unsigned int) floor( ( yC/mm - table_start[1]/mm ) / (cell_size[1]/mm ) ) ;
1307 Iz = (
unsigned int) floor( ( zC/mm - table_start[2]/mm ) / (cell_size[2]/mm ) ) ;
1309 if( fabs( table_start[0]/mm + Ix*cell_size[0]/mm - xC) > fabs( table_start[0]/mm + (Ix+1)*cell_size[0]/mm - xC) ) Ix++;
1310 if( fabs( table_start[1]/mm + Iy*cell_size[1]/mm - yC) > fabs( table_start[1]/mm + (Iy+1)*cell_size[1]/mm - yC) ) Iy++;
1311 if( fabs( table_start[2]/mm + Iz*cell_size[2]/mm - zC) > fabs( table_start[2]/mm + (Iz+1)*cell_size[2]/mm - zC) ) Iz++;
1316 if( Ix < B3DCartX.size() && Ix < B3DCartY.size() && Ix < B3DCartZ.size())
1317 if( Iy < B3DCartX[Ix].size() && Iy < B3DCartY[Ix].size() && Iy < B3DCartZ[Ix].size())
1318 if( Iz < B3DCartX[Ix][Iy].size() && Iz < B3DCartY[Ix][Iy].size() && Iz < B3DCartZ[Ix][Iy].size())
1321 mfield[0] = B3DCartX[Ix][Iy][Iz];
1322 mfield[1] = B3DCartY[Ix][Iy][Iz];
1323 mfield[2] = B3DCartZ[Ix][Iy][Iz];
1325 if(MGN_VERBOSITY>6 && FIRST_ONLY != 99)
1327 cout << hd_msg <<
" Segmented Field: Cart. coord. (cm), indexes and field values (gauss):" << endl;
1328 cout <<
" x=" << point[0]/cm <<
" " ;
1329 cout <<
"y=" << point[1]/cm <<
" ";
1330 cout <<
"z=" << point[2]/cm <<
" ";
1331 cout <<
"Ix=" << Ix <<
" ";
1332 cout <<
"Iy=" << Iy <<
" ";
1333 cout <<
"Iz=" << Iz <<
" ";
1334 cout <<
"lBx=" << mfield[0]/gauss <<
" ";
1335 cout <<
"lBy=" << mfield[1]/gauss <<
" ";
1336 cout <<
"lBz=" << mfield[2]/gauss << endl ;
1339 for(
int i=0; i<3; i++) Field[i].push_back(mfield[i]);
1346 for(
unsigned int i=0; i<Field[0].size(); i++)
1347 for(
int j=0; j<3; j++)
1348 Bfield[j] += Field[j][i];
1350 if(MGN_VERBOSITY>5 && FIRST_ONLY != 99)
1352 cout << hd_msg <<
" Total Field: coordinates (cm), magnetic field values (gauss):" << endl ;
1353 cout <<
" x=" << point[0]/cm <<
" " ;
1354 cout <<
"y=" << point[1]/cm <<
" ";
1355 cout <<
"z=" << point[2]/cm <<
" ";
1356 cout <<
"Bx=" << Bfield[0]/gauss <<
" ";
1357 cout <<
"By=" << Bfield[1]/gauss <<
" ";
1358 cout <<
"Bz=" << Bfield[2]/gauss << endl << endl;
1361 if(MGN_VERBOSITY == 99)
double scale_factor
Scale factor.
void create_MFM()
Creates the G4 Magnetic Field Manager.
double segm_phi_span
azimuthal span of the map for phi-segmented fields
map< string, MagneticField > get_magnetic_Fields(gemc_opts Opt)
Fills magnetic field maps from Database.
string gemc_tostring(QString input)
void init_MFM()
Initialize Field Manager Pointer to NULL.
int nsegments
number of segments
string magnitude
Magnetic Field magnitude infos.
string swim_method
Magnetic Field Swim Method.
gemc_opts gemcOpt
gemc options map
map< string, opts > args
Options map.
string name
Magnetic Field identifier.
void GetFieldValue(const double x[3], double *Bfield) const
string TrimSpaces(string in)
Removes leading and trailing spaces.
MappedField * mappedfield
Mapped Magnetic Field.
double get_number(string)
Returns dimension from string, i.e. 100*cm.
vector< opts > get_args(string)
get a vector of arguments matching a string
string type
Type of Magnetic Field.
string description
Field Description.