11 #include <geometry/bfieldmap/BFieldComponentQuad.h>
13 #include <framework/utilities/FileSystem.h>
14 #include <framework/logging/Logger.h>
15 #include <framework/gearbox/Unit.h>
16 #include <framework/gearbox/Const.h>
18 #include <boost/iostreams/filtering_stream.hpp>
19 #include <boost/iostreams/device/file.hpp>
25 namespace io = boost::iostreams;
35 template <
class ForwardIterator,
class T,
class Compare>
36 ForwardIterator linear_sentinel(ForwardIterator it,
const T& val, Compare comp)
39 if (comp(val, *it))
break;
45 void BFieldComponentQuad::initialize()
48 if (m_mapFilenameHER.empty()) {
49 B2FATAL(
"The filename for the HER quadrupole magnetic field component is empty !");
52 if (m_mapFilenameLER.empty()) {
53 B2FATAL(
"The filename for the LER quadrupole magnetic field component is empty !");
56 if (m_apertFilenameHER.empty()) {
57 B2FATAL(
"The filename for the HER beam pipe aperture is empty !");
60 if (m_apertFilenameLER.empty()) {
61 B2FATAL(
"The filename for the LER beam pipe aperture is empty !");
66 string fullPathMapHER = FileSystem::findFile(
"/data/" + m_mapFilenameHER);
67 if (!FileSystem::fileExists(fullPathMapHER)) {
68 B2FATAL(
"The HER quadrupole magnetic field map file '" << m_mapFilenameHER <<
"' could not be found !");
71 string fullPathMapLER = FileSystem::findFile(
"/data/" + m_mapFilenameLER);
72 if (!FileSystem::fileExists(fullPathMapLER)) {
73 B2FATAL(
"The LER quadrupole magnetic field map file '" << m_mapFilenameLER <<
"' could not be found !");
76 string fullPathMapHERleak = FileSystem::findFile(
"/data/" + m_mapFilenameHERleak);
77 if (!FileSystem::fileExists(fullPathMapHERleak)) {
78 B2FATAL(
"The HERleak quadrupole magnetic field map file '" << m_mapFilenameHERleak <<
"' could not be found !");
81 string fullPathApertHER = FileSystem::findFile(
"/data/" + m_apertFilenameHER);
82 if (!FileSystem::fileExists(fullPathApertHER)) {
83 B2FATAL(
"The HER aperture file '" << m_apertFilenameHER <<
"' could not be found !");
86 string fullPathApertLER = FileSystem::findFile(
"/data/" + m_apertFilenameLER);
87 if (!FileSystem::fileExists(fullPathApertLER)) {
88 B2FATAL(
"The LER aperture file '" << m_apertFilenameLER <<
"' could not be found !");
112 io::filtering_istream fieldMapFileHER, fieldMapFileLER, fieldMapFileHERleak;
113 fieldMapFileHER.push(io::file_source(fullPathMapHER));
114 fieldMapFileLER.push(io::file_source(fullPathMapLER));
115 fieldMapFileHERleak.push(io::file_source(fullPathMapHERleak));
118 auto readLenseParameters = [](istream & IN) -> vector<ParamPoint> {
119 vector<ParamPoint> r;
122 while (IN >> name >> t.s >> t.L >> t.K0 >> t.K1 >> t.SK0 >> t.SK1 >> t.ROTATE >> t.DX >> t.DY)
136 std::vector<ParamPoint> params_her, params_ler, params_herl;
137 params_her = readLenseParameters(fieldMapFileHER);
138 params_ler = readLenseParameters(fieldMapFileLER);
139 params_herl = readLenseParameters(fieldMapFileHERleak);
144 auto readAperturePoints = [
this](istream & IN) -> vector<ApertPoint> {
145 vector<ApertPoint> r;
147 while (IN >> t.s >> t.r)
151 t.s /= 10; t.r /= 10;
153 m_maxr2 = max(m_maxr2, t.r);
155 r.push_back({numeric_limits<double>::infinity(), m_maxr2});
159 io::filtering_istream apertFileHER, apertFileLER;
160 apertFileHER.push(io::file_source(fullPathApertHER));
161 apertFileLER.push(io::file_source(fullPathApertLER));
163 m_ah = readAperturePoints(apertFileHER);
164 m_al = readAperturePoints(apertFileLER);
174 auto proc3 = [](
const vector<ParamPoint>& in,
double p0) -> vector<ParamPoint3> {
175 vector<ParamPoint3> out;
176 out.resize(in.size());
177 auto it = out.begin();
178 for (
auto b = in.begin(); b != in.end(); ++b, ++it)
196 #define ROTATE_DIRECTION 1 // 1: default, 0: rotate-off, -1: inversely rotate
197 #if ROTATE_DIRECTION==0
198 double sphi = 0, cphi = 1;
201 sincos(-b->ROTATE * (M_PI / 180), &sphi, &cphi);
202 #if ROTATE_DIRECTION==-1
206 double s2phi = 2 * cphi * sphi;
207 double c2phi = cphi * cphi - sphi * sphi;
208 double tp = DX * SK1 + DY * K1;
209 double tm = DY * SK1 - DX * K1;
211 t.mxx = K1 * s2phi + SK1 * c2phi;
212 t.mxy = -SK1 * s2phi + K1 * c2phi;
213 t.mx0 = tm * s2phi - tp * c2phi + SK0 * cphi + K0 * sphi;
215 t.myx = -SK1 * s2phi + K1 * c2phi;
216 t.myy = -K1 * s2phi - SK1 * c2phi;
217 t.my0 = tp * s2phi + tm * c2phi + K0 * cphi - SK0 * sphi;
222 const double c = Const::speedOfLight / (Unit::m / Unit::s) / 100;
223 const double p0_HER = 7.0e+9 / c, p0_LER = 4.0e+9 / c;
225 m_h3 = proc3(params_her, p0_HER);
226 vector<ParamPoint3> hleak3 = proc3(params_herl, p0_HER);
227 m_l3 = proc3(params_ler, p0_LER);
238 auto merge = [](vector<ParamPoint3>& v,
const vector<ParamPoint3>& a) {
239 for (
const auto& t : a) {
240 auto i = upper_bound(v.begin(), v.end(), t.s, [](
double s,
const ParamPoint3 & b) {return s < b.s;});
241 if (i == v.end())
continue;
243 if (p.s == t.s && p.L == t.L)
257 auto getranges = [](
const vector<ParamPoint3>& v) {
259 double s0 = v[0].s, smax = v.back().s + v.back().L;
260 for (
int i = 0, N = v.size(); i < N - 1; i++) {
262 double sn = t0.s + t0.L;
263 if (abs(sn - t1.s) > 1e-10) {
264 r.push_back({s0, sn});
268 r.push_back({s0, smax});
272 m_ranges_her = getranges(m_h3);
273 m_ranges_ler = getranges(m_l3);
275 const double inf = numeric_limits<double>::infinity();
277 m_ranges_her.insert(m_ranges_her.begin(), { -inf, -inf});
278 m_ranges_her.insert(m_ranges_her.end(), {inf, inf});
279 m_ranges_ler.insert(m_ranges_ler.begin(), { -inf, -inf});
280 m_ranges_ler.insert(m_ranges_ler.end(), {inf, inf});
288 auto associate_aperture = [](
const vector<ApertPoint>& ap,
const ranges_t& v) {
289 auto less = [](
double s,
const ApertPoint & b) {
return s < b.s;};
290 vector<std::vector<ApertPoint>::const_iterator> res;
292 auto i0 = upper_bound(ap.begin(), ap.end(), r.r0, less);
293 if (i0 == ap.begin() || i0 == ap.end())
continue;
294 res.push_back(i0 - 1);
298 m_offset_ap_her = associate_aperture(m_ah, m_ranges_her);
299 m_offset_ap_ler = associate_aperture(m_al, m_ranges_ler);
307 auto associate_lenses = [](
const vector<ParamPoint3>& ap,
const ranges_t& v) {
308 vector<std::vector<ParamPoint3>::const_iterator> res;
310 auto i0 = find_if(ap.begin(), ap.end(), [r](
const ParamPoint3 & b) {return abs(b.s - r.r0) < 1e-10;});
311 if (i0 == ap.end())
continue;
316 m_offset_pp_her = associate_lenses(m_h3, m_ranges_her);
317 m_offset_pp_ler = associate_lenses(m_l3, m_ranges_ler);
320 double BFieldComponentQuad::getApertureHER(
double s)
const
322 int i = getRange(s, m_ranges_her);
324 return getAperture(s, m_offset_ap_her[i]);
327 double BFieldComponentQuad::getApertureLER(
double s)
const
329 int i = getRange(s, m_ranges_ler);
331 return getAperture(s, m_offset_ap_ler[i]);
334 int BFieldComponentQuad::getRange(
double s,
const ranges_t& r)
const
336 auto it0 = r.begin() + 1;
337 auto it = linear_sentinel(it0, s, [](
double s_,
const range_t& r_) {
return s_ <= r_.
r0;});
338 if (s > (--it)->r1)
return -1;
342 double BFieldComponentQuad::getAperture(
double s, std::vector<ApertPoint>::const_iterator jt0)
const
344 auto jt = linear_sentinel(jt0, s, [](
double s_,
const ApertPoint & r) {
return s_ <= r.s;});
346 return p1.r + (p2.r - p1.r) / (p2.s - p1.s) * (s - p1.s);
351 const double sa = sin(0.0415), ca = cos(0.0415);
356 double xc = v.x() * ca, zs = v.z() * sa, zc = v.z() * ca, xs = v.x() * sa;
360 double r2h = vh.Perp2(), r2l = vl.Perp2();
365 int i = getRange(s, m_ranges_her);
367 double r = getAperture(s, m_offset_ap_her[i]);
369 auto kt = m_offset_pp_her[i] +
static_cast<unsigned int>(s - m_ranges_her[i + 1].r0);
370 double Bx = kt->getBx(vh.x(), vh.y());
371 double By = kt->getBy(vh.x(), vh.y());
372 B.SetXYZ(Bx * ca, -By, -Bx * sa);
378 int i = getRange(s, m_ranges_ler);
380 double r = getAperture(s, m_offset_ap_ler[i]);
382 auto kt = m_offset_pp_ler[i] +
static_cast<unsigned int>(s - m_ranges_ler[i + 1].r0);
383 double Bx = kt->getBx(vl.x(), vl.y());
384 double By = kt->getBy(vl.x(), vl.y());
385 B.SetXYZ(Bx * ca, -By, Bx * sa);