Belle II Software development
BeamlineFieldMapInterpolation Class Reference

The BeamlineFieldMapInterpolation class. More...

Public Member Functions

const TriangularInterpolationgetTriangularInterpolation () const
 Expose the triangular interpolation to outside.
 
 BeamlineFieldMapInterpolation ()=default
 Default constructor.
 
 ~BeamlineFieldMapInterpolation ()=default
 Default destructor.
 
void init (const string &fieldmapname, const string &interpolname, double validRadius)
 Initializes the magnetic field component.
 
int zIndexAndWeight (double z, double &w1) const
 For a given Z coordinate calculate the index of Z slice and corresponding weight.
 
bool inRange (const ROOT::Math::XYZVector &v) const
 Check the space point if the interpolation exists.
 
ROOT::Math::XYZVector interpolateField (const ROOT::Math::XYZVector &v) const
 Interpolate the magnetic field vector at the specified space point.
 

Protected Attributes

vector< ROOT::Math::XYZVector > m_B
 Buffer for the magnetic field map.
 
TriangularInterpolation m_triInterpol
 Object to locate point in a triangular mesh.
 
int m_nxy {0}
 Number of field points in XY plane.
 
int m_nz {0}
 Number of field slices in Z direction.
 
int m_nz1 {0}
 Start Z slice number for the finer Z grid.
 
int m_nz2 {0}
 End Z slice number for the finer Z grid.
 
int m_nr {0}
 Number of grid points in R direction.
 
int m_nphi {0}
 Number of grid points in Phi direction.
 
double m_rj {0}
 Separation radius between triangular and cylindrical meshes.
 
double m_rj2 {0}
 Square of the separation radius between triangular and cylindrical meshes.
 
double m_zj {0}
 Z border of finer Z grid.
 
double m_dz0 {0}
 Coarse Z grid pitch.
 
double m_dz1 {0}
 Finer Z grid pitch.
 
double m_idz0 {0}
 Inverse of coarse Z grid pitch.
 
double m_idz1 {0}
 Inverse of finer Z grid pitch.
 
double m_idphi {0}
 Repciprocal of Phi grid.
 
double m_idr {0}
 Repciprocal of R grid.
 
double m_rmax {0}
 Maximal radius where interpolation is still valid.
 
double m_zmax {0}
 Maximal Z where interpolation is still valid.
 

Detailed Description

The BeamlineFieldMapInterpolation class.

This class interpolates a magnetic field map around beamline. The magnetic field map is stored as a grid in cylindrical coordinates for outer radiuses and triangular mesh for inner part It is defined by a maximum radius and a maximum z value, a pitch size in both, r and z, and the number of grid points.

Definition at line 286 of file BFieldComponentBeamline.cc.

Member Function Documentation

◆ getTriangularInterpolation()

const TriangularInterpolation & getTriangularInterpolation ( ) const
inlinenodiscard

Expose the triangular interpolation to outside.

Returns
constant reference to the interpolation

Definition at line 293 of file BFieldComponentBeamline.cc.

293{return m_triInterpol;}

◆ init()

void init ( const string & fieldmapname,
const string & interpolname,
double validRadius )
inline

Initializes the magnetic field component.

This method opens the magnetic field map file and triangular mesh.

Parameters
fieldmapnameFile name containing the field map
interpolnameFile name containing triangular mesh
validRadiusMaximum radius up to which interpolation is valid

Definition at line 311 of file BFieldComponentBeamline.cc.

312 {
313 if (fieldmapname.empty()) {
314 B2ERROR("The filename for the beamline magnetic field component is empty !");
315 return;
316 }
317 std::string l_fieldmapname = FileSystem::findFile("/data/" + fieldmapname);
318
319 if (interpolname.empty()) {
320 B2ERROR("The filename for the triangulation of the beamline magnetic field component is empty !");
321 return;
322 }
323 std::string l_interpolname = FileSystem::findFile("/data/" + interpolname);
324
325 m_rmax = validRadius;
326
327 B2DEBUG(50, "Delaunay triangulation of the beamline field map: " << l_interpolname);
328 B2DEBUG(50, "Beamline field map: " << l_fieldmapname);
329
330 // load interpolation triangles
331 ifstream INd(l_interpolname);
332 int nts; INd >> nts;
333 B2DEBUG(50, "Total number of triangles: " << nts);
334 vector<triangle_t> ts;
335 ts.reserve(nts);
336 // load triangle definitions from file
337 {
338 triangle_t p;
339 while (INd >> nts >> p.j0 >> p.j1 >> p.j2 >> p.n0 >> p.n1 >> p.n2) ts.push_back(p);
340 }
341
342 //Load the map file
343 io::filtering_istream IN;
344 IN.push(io::gzip_decompressor());
345 IN.push(io::file_source(l_fieldmapname));
346
347 int nrphi;
348 IN >> nrphi >> m_rj >> m_nr >> m_nphi;
349 IN >> m_nz >> m_zj >> m_dz0 >> m_dz1;
350 m_idphi = m_nphi / M_PI;
351 m_rj2 = m_rj * m_rj;
352 m_idz0 = 1 / m_dz0;
353 m_idz1 = 1 / m_dz1;
354 int nz0 = 2 * int(m_zj / m_dz0);
355 m_zmax = (m_nz - (nz0 + 1)) / 2 * m_dz1 + m_zj;
356 m_nz1 = (m_nz - (nz0 + 1)) / 2;
357 m_nz2 = m_nz1 + nz0;
358 // cout<<_zmax<<" "<<nz0<<" "<<m_nz1<<" "<<m_nz2<<endl;
359
360 struct cs_t {double c, s;};
361 vector<cs_t> cs(nrphi);
362 vector<xy_t> pc;
363 vector<ROOT::Math::XYZVector> tbc;
364 pc.reserve(nrphi);
365 char cbuf[256]; IN.getline(cbuf, 256);
366 double rmax = 0;
367 for (int j = 0; j < nrphi; j++) {
368 IN.getline(cbuf, 256);
369 char* next = cbuf;
370 double r = strtod(next, &next);
371 double phi = strtod(next, &next);
372 strtod(next, &next);
373 double Br = strtod(next, &next);
374 double Bphi = strtod(next, &next);
375 double Bz = strtod(next, nullptr);
376 r *= 100;
377 rmax = std::max(r, rmax);
378 if (phi == 0) {
379 cs[j] = { 1, 0};
380 } else if (phi == 180) {
381 cs[j] = { -1, 0};
382 } else {
383 phi *= M_PI / 180;
384 cs[j] = {cos(phi), sin(phi)};
385 }
386 double x = r * cs[j].c, y = r * cs[j].s;
387 pc.push_back({x, y});
388 if (cs[j].s == 0) Bphi = 0;
389 double Bx = Br * cs[j].c - Bphi * cs[j].s;
390 double By = Br * cs[j].s + Bphi * cs[j].c;
391 tbc.emplace_back(Bx, By, Bz);
392 }
393 // cout<<"Field map has data points up to R="<<rmax<<" cm."<<endl;
394
395 m_idr = m_nr / (rmax - m_rj);
396 m_rmax = std::min(m_rmax, rmax);
397 bool reduce = m_rj > m_rmax;
398
399 // if valid radius is within the triangular mesh try to reduce
400 // field map keeping only points which participate to the
401 // interpolation
402 vector<bool> ip;
403 if (reduce) {
404 ip.resize(nrphi, false);
405 vector<bool> it(ts.size(), false);
406 auto inside = [this](const xy_t & p)->bool{
407 return p.x * p.x + p.y * p.y < m_rmax * m_rmax;
408 };
409
410 for (int i = 0, imax = ts.size(); i < imax; i++) {
411 const triangle_t& p = ts[i];
412 const xy_t& p0 = pc[p.j0], &p1 = pc[p.j1], &p2 = pc[p.j2];
413 if (inside(p0) || inside(p1) || inside(p2)) {
414 it[i] = true;
415 ip[p.j0] = true;
416 ip[p.j1] = true;
417 ip[p.j2] = true;
418 }
419 }
420
421 vector<short int> pindx(nrphi, -1);
422 int rnp = 0;
423 for (int i = 0, imax = ip.size(); i < imax; i++) {
424 if (ip[i]) pindx[i] = rnp++;
425 }
426 vector<xy_t> rpc;
427 rpc.reserve(rnp);
428 for (int i = 0, imax = pc.size(); i < imax; i++) {
429 if (ip[i]) rpc.push_back(pc[i]);
430 }
431
432 vector<short int> tindx(ts.size(), -1);
433 short int rnt = 0;
434 for (int i = 0, imax = it.size(); i < imax; i++) {
435 if (it[i]) tindx[i] = rnt++;
436 }
437 vector<triangle_t> rts;
438 rts.reserve(rnt);
439 short int nt = ts.size();
440 auto newind = [&nt, &tindx, &rnt](short int n) -> short int {return (n < nt) ? tindx[n] : rnt;};
441 for (int i = 0, imax = ts.size(); i < imax; i++) {
442 if (it[i]) {
443 const triangle_t& t = ts[i];
444 rts.push_back({pindx[t.j0], pindx[t.j1], pindx[t.j2], newind(t.n0), newind(t.n1), newind(t.n2)});
445 }
446 }
447
448 B2DEBUG(50, "Reduce map size to cover only region R<" << m_rmax << " cm: Ntriangles=" << rnt << " Nxypoints = " << rnp <<
449 " Nzslices=" << m_nz << " NBpoints = " << rnp * m_nz);
450 std::swap(rpc, pc);
451 std::swap(rts, ts);
452 } else {
453 ip.resize(nrphi, true);
454 }
455 m_nxy = pc.size();
456
457 m_triInterpol.init(pc, ts, 0.1);
458
459 vector<ROOT::Math::XYZVector> bc(m_nxy * m_nz);
460 unsigned int count = 0;
461 for (int i = 0; i < nrphi; i++) {
462 if (ip[i]) bc[count++] = ROOT::Math::XYZVector(tbc[i]);
463 }
464
465 for (int i = 1; i < m_nz; ++i) {
466 for (int j = 0; j < nrphi; j++) {
467 IN.getline(cbuf, 256);
468 if (!ip[j]) continue;
469 char* next = cbuf;
470 next = strchr(next, ' ');
471 next = strchr(next + 1, ' ');
472 next = strchr(next + 1, ' ');
473 double Br = strtod(next, &next);
474 double Bphi = strtod(next, &next);
475 double Bz = strtod(next, nullptr);
476 if (cs[j].s == 0) Bphi = 0;
477 double Bx = Br * cs[j].c - Bphi * cs[j].s;
478 double By = Br * cs[j].s + Bphi * cs[j].c;
479 bc[count++].SetXYZ(Bx, By, Bz);
480 }
481 }
482 assert(count == bc.size());
483 swap(bc, m_B);
484 }

◆ inRange()

bool inRange ( const ROOT::Math::XYZVector & v) const
inlinenodiscard

Check the space point if the interpolation exists.

Parameters
vThe space point in Cartesian coordinates (x,y,z) in [cm] at which the interpolation exists.
Returns
The magnetic field vector at the given space point in [T]. Returns false if the space point lies outside the valid region.

Definition at line 528 of file BFieldComponentBeamline.cc.

529 {
530 if (std::abs(v.Z()) > m_zmax) return false;
531 double R2 = v.X() * v.X() + v.Y() * v.Y();
532 if (R2 > m_rmax * m_rmax) return false;
533 return true;
534 }

◆ interpolateField()

ROOT::Math::XYZVector interpolateField ( const ROOT::Math::XYZVector & v) const
inlinenodiscard

Interpolate the magnetic field vector at the specified space point.

Parameters
vThe space point in Cartesian coordinates (x,y,z) in [cm] at which the magnetic field vector should be calculated.
Returns
The magnetic field vector at the given space point in [T]. Returns a zero vector (0,0,0) if the space point lies outside the region described by the component.

Definition at line 545 of file BFieldComponentBeamline.cc.

546 {
547 ROOT::Math::XYZVector res = {0, 0, 0};
548 double R2 = v.X() * v.X() + v.Y() * v.Y();
549 if (R2 > m_rmax * m_rmax) return res;
550 double wz1;
551 int iz = zIndexAndWeight(v.Z(), wz1);
552 if (iz < 0) return res;
553 double wz0 = 1 - wz1;
554
555 if (R2 < m_rj2) { // triangular interpolation
556 xy_t xy = {v.X(), std::abs(v.Y())};
557 double w0, w1, w2;
558 short int it = m_triInterpol.findTriangle(xy);
559 m_triInterpol.weights(it, xy, w0, w1, w2);
560 auto t = m_triInterpol.getTriangles().begin() + it;
561 int j0 = t->j0, j1 = t->j1, j2 = t->j2;
562 const ROOT::Math::XYZVector* B = m_B.data() + m_nxy * iz;
563 ROOT::Math::XYZVector b = (B[j0] * w0 + B[j1] * w1 + B[j2] * w2) * wz0;
564 B += m_nxy; // next z-slice
565 b += (B[j0] * w0 + B[j1] * w1 + B[j2] * w2) * wz1;
566 res = b;
567 } else {// r-phi grid
568 double r = sqrt(R2), phi = atan2(std::abs(v.Y()), v.X());
569 double fr = (r - m_rj) * m_idr;
570 double fphi = phi * m_idphi;
571
572 int ir = static_cast<int>(fr);
573 int iphi = static_cast<int>(fphi);
574
575 ir -= (ir == m_nr);
576 iphi -= (iphi == m_nphi);
577
578 double wr1 = fr - ir, wr0 = 1 - wr1;
579 double wphi1 = fphi - iphi, wphi0 = 1 - wphi1;
580 const int nr1 = m_nr + 1, nphi1 = m_nphi + 1;
581 int j00 = m_nxy - nr1 * (nphi1 - iphi) + ir;
582 int j01 = j00 + 1;
583 int j10 = j00 + nr1;
584 int j11 = j01 + nr1;
585
586 double w00 = wr0 * wphi0, w01 = wphi0 * wr1, w10 = wphi1 * wr0, w11 = wphi1 * wr1;
587 const ROOT::Math::XYZVector* B = m_B.data() + m_nxy * iz;
588 ROOT::Math::XYZVector b = (B[j00] * w00 + B[j01] * w01 + B[j10] * w10 + B[j11] * w11) * wz0;
589 B += m_nxy; // next z-slice
590 b += (B[j00] * w00 + B[j01] * w01 + B[j10] * w10 + B[j11] * w11) * wz1;
591 res = b;
592 }
593 if (v.Y() < 0) res.SetY(-res.Y());
594 return res;
595 }
double sqrt(double a)
sqrt for double
Definition beamHelpers.h:28

◆ zIndexAndWeight()

int zIndexAndWeight ( double z,
double & w1 ) const
inline

For a given Z coordinate calculate the index of Z slice and corresponding weight.

Parameters
zZ coordinate
w1weight of the slice
Returns
the index of Z slice. Returns -1 if Z coordinate is outside valid region region.

Definition at line 495 of file BFieldComponentBeamline.cc.

496 {
497 if (std::abs(z) > m_zmax) return -1;
498 double fz;
499 int iz = 0;
500 if (z < - m_zj) {
501 fz = (z + m_zmax) * m_idz1;
502 } else if (z < m_zj) {
503 fz = (z + m_zj) * m_idz0;
504 iz = m_nz1;
505 } else {
506 fz = (z - m_zj) * m_idz1;
507 iz = m_nz2;
508 }
509 int jz = static_cast<int>(fz);
510 w1 = fz - jz;
511 iz += jz;
512 if (iz == m_nz) {
513 --iz;
514 w1 = 1;
515 }
516 return iz;
517 }

Member Data Documentation

◆ m_B

vector<ROOT::Math::XYZVector> m_B
protected

Buffer for the magnetic field map.

Definition at line 598 of file BFieldComponentBeamline.cc.

◆ m_dz0

double m_dz0 {0}
protected

Coarse Z grid pitch.

Definition at line 620 of file BFieldComponentBeamline.cc.

620{0};

◆ m_dz1

double m_dz1 {0}
protected

Finer Z grid pitch.

Definition at line 622 of file BFieldComponentBeamline.cc.

622{0};

◆ m_idphi

double m_idphi {0}
protected

Repciprocal of Phi grid.

Definition at line 628 of file BFieldComponentBeamline.cc.

628{0};

◆ m_idr

double m_idr {0}
protected

Repciprocal of R grid.

Definition at line 630 of file BFieldComponentBeamline.cc.

630{0};

◆ m_idz0

double m_idz0 {0}
protected

Inverse of coarse Z grid pitch.

Definition at line 624 of file BFieldComponentBeamline.cc.

624{0};

◆ m_idz1

double m_idz1 {0}
protected

Inverse of finer Z grid pitch.

Definition at line 626 of file BFieldComponentBeamline.cc.

626{0};

◆ m_nphi

int m_nphi {0}
protected

Number of grid points in Phi direction.

Definition at line 612 of file BFieldComponentBeamline.cc.

612{0};

◆ m_nr

int m_nr {0}
protected

Number of grid points in R direction.

Definition at line 610 of file BFieldComponentBeamline.cc.

610{0};

◆ m_nxy

int m_nxy {0}
protected

Number of field points in XY plane.

Definition at line 602 of file BFieldComponentBeamline.cc.

602{0};

◆ m_nz

int m_nz {0}
protected

Number of field slices in Z direction.

Definition at line 604 of file BFieldComponentBeamline.cc.

604{0};

◆ m_nz1

int m_nz1 {0}
protected

Start Z slice number for the finer Z grid.

Definition at line 606 of file BFieldComponentBeamline.cc.

606{0};

◆ m_nz2

int m_nz2 {0}
protected

End Z slice number for the finer Z grid.

Definition at line 608 of file BFieldComponentBeamline.cc.

608{0};

◆ m_rj

double m_rj {0}
protected

Separation radius between triangular and cylindrical meshes.

Definition at line 614 of file BFieldComponentBeamline.cc.

614{0};

◆ m_rj2

double m_rj2 {0}
protected

Square of the separation radius between triangular and cylindrical meshes.

Definition at line 616 of file BFieldComponentBeamline.cc.

616{0};

◆ m_rmax

double m_rmax {0}
protected

Maximal radius where interpolation is still valid.

Definition at line 632 of file BFieldComponentBeamline.cc.

632{0};

◆ m_triInterpol

TriangularInterpolation m_triInterpol
protected

Object to locate point in a triangular mesh.

Definition at line 600 of file BFieldComponentBeamline.cc.

◆ m_zj

double m_zj {0}
protected

Z border of finer Z grid.

Definition at line 618 of file BFieldComponentBeamline.cc.

618{0};

◆ m_zmax

double m_zmax {0}
protected

Maximal Z where interpolation is still valid.

Definition at line 634 of file BFieldComponentBeamline.cc.

634{0};

The documentation for this class was generated from the following file: