Skip to content

Commit 80beba6

Browse files
authored
Merge pull request #404 from jgray-19/fix_sbend_face
Backtracking Improvements
2 parents 41c30f4 + de639e2 commit 80beba6

File tree

4 files changed

+120
-59
lines changed

4 files changed

+120
-59
lines changed

src/mad_dynmap.cpp

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,18 +1193,32 @@ inline void bend_face (cflw<M> &m, num_t lw, const V &h)
11931193
if (m.sdir == 1) p.px += k0hq*sqr(p.x);
11941194

11951195
T dpp = 1 + 2/m.beta*p.pt + sqr(p.pt);
1196+
T y2 = sqr(p.y);
11961197
T _pt2 = 1/(dpp - sqr(p.px));
11971198
T xi = 2*k0hq * sqrt(dpp)*_pt2;
11981199
T dxi_px = 2*p.px*xi *_pt2;
1199-
T dxi_ddel = -2 *xi*(1+p.pt)*_pt2;
1200-
T y2 = sqr(p.y);
1201-
1202-
p.x /= 1-dxi_px*y2;
1203-
p.px -= xi*y2;
1204-
p.py -= 2*xi*p.x*p.y;
1205-
p.t += dxi_ddel*p.x*y2;
1200+
1201+
if (m.sdir == -1) {
1202+
T npx = p.px - xi*y2;
1203+
_pt2 = 1/(dpp - sqr(npx));
1204+
xi = 2*k0hq * sqrt(dpp)*_pt2;
1205+
dxi_px = 2*npx*xi *_pt2;
1206+
}
12061207

1207-
if (m.sdir == -1) p.px += k0hq*sqr(p.x);
1208+
T dxi_ddel = -2 *xi*(1+p.pt)*_pt2;
1209+
if (m.sdir == 1){
1210+
p.x /= 1-dxi_px*y2;
1211+
p.px -= xi*y2;
1212+
p.py -= 2*xi*p.x*p.y;
1213+
p.t += dxi_ddel*p.x*y2;
1214+
} else {
1215+
p.t += dxi_ddel*p.x*y2;
1216+
p.py -= 2*xi*p.x*p.y;
1217+
1218+
p.x /= 1-dxi_px*y2;
1219+
p.px -= xi*y2;
1220+
p.px += k0hq*sqr(p.x);
1221+
}
12081222
}
12091223
mdump(1);
12101224
}
@@ -1306,12 +1320,13 @@ inline void bend_fringe (cflw<M> &m, num_t lw)
13061320
T fi2 = -2*co1*xyp*_yp2 - co3*2*xp*xyp *pz;
13071321
T fi3 = - co3*(1 + xp2*(1+yp2));
13081322

1309-
T kx = fi1*(1+xp2)*_pz + fi2*xyp*_pz - fi3*xp;
13101323
T ky = fi1*xyp*_pz + fi2*yp2*_pz - fi3*yp;
1311-
T kz = fi1*tfac*xp*_pz2 + fi2*tfac*yp*_pz2 - fi3*tfac*_pz;
1324+
T y = 2*p.y / (1 + sqrt(1-2*ky*p.y));
13121325

13131326
if (m.sdir == 1) {
1314-
T y = 2*p.y / (1 + sqrt(1-2*ky*p.y));
1327+
// Only calculate kx and kz once
1328+
T kx = fi1*(1+xp2)*_pz + fi2*xyp*_pz - fi3*xp;
1329+
T kz = fi1*tfac*xp*_pz2 + fi2*tfac*yp*_pz2 - fi3*tfac*_pz;
13151330
T y2 = sqr(y);
13161331

13171332
p.x += 0.5*kx*y2;
@@ -1320,11 +1335,34 @@ inline void bend_fringe (cflw<M> &m, num_t lw)
13201335
p.y = y;
13211336
} else { // need to reverse y-dependence
13221337
T y2 = sqr(p.y);
1338+
// recalculate kx, ky and kz with a new py (Work out what it probably was)
1339+
T npy = p.py + (4*c3*y2 + b0*tan(fi0))*y;
1340+
1341+
pz = sqrt(dpp - sqr(p.px) - sqr(npy));
1342+
_pz = 1/pz;
1343+
_pz2 = sqr(_pz);
1344+
1345+
xp = p.px/pz, yp = npy/pz;
1346+
xyp = xp*yp , yp2 = 1+sqr(yp);
1347+
xp2 = sqr(xp), _yp2 = 1/yp2;
1348+
1349+
fi0 = atan((xp*_yp2)) - c2*(1 + xp2*(1+yp2))*pz;
1350+
co2 = b0/sqr(cos(fi0));
1351+
co1 = co2/(1 + sqr(xp*_yp2))*_yp2;
1352+
co3 = co2*c2;
1353+
1354+
fi1 = co1 - co3*2*xp*(1+yp2)*pz;
1355+
fi2 = -2*co1*xyp*_yp2 - co3*2*xp*xyp *pz;
1356+
fi3 = - co3*(1 + xp2*(1+yp2));
1357+
1358+
T kx = fi1*(1+xp2)*_pz + fi2*xyp*_pz - fi3*xp;
1359+
ky = fi1*xyp*_pz + fi2*yp2*_pz - fi3*yp;
1360+
T kz = fi1*tfac*xp*_pz2 + fi2*tfac*yp*_pz2 - fi3*tfac*_pz;
13231361

13241362
p.x -= 0.5*kx*y2;
13251363
p.py += (4*c3*y2 + b0*tan(fi0))*p.y;
13261364
p.t -= (0.5*kz + c3*y2*sqr(relp)*tfac)*y2;
1327-
p.y *= 0.5*(1 + sqrt(1-2*ky*p.y));
1365+
p.y -= y2*ky/2;
13281366
}
13291367
}
13301368
mdump(1);

src/madl_dynmap.mad

Lines changed: 66 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1777,21 +1777,33 @@ function bend_face (elm, m, lw, h) -- [NEWFACE] --
17771777
px = px + k0hq*x^2
17781778
end
17791779

1780-
-- This is still not fully revesible in 3rd and 4th order, due to self dependance of px
1781-
local dpp = 1 + 2/beta*pt + pt^2
1782-
local _pt2 = 1/(dpp - px^2)
1783-
local xi = 2*k0hq*sqrt(dpp)*_pt2
1784-
local dxi_px = 2*px*xi *_pt2
1785-
local dxi_ddel = -2 *xi*(1+pt) *_pt2
1786-
local y2 = y^2
1787-
1788-
x = x / (1-dxi_px*y2) -- this affects reversibility also, for py
1789-
px = px - xi*y2
1790-
py = py - 2*xi*x*y
1791-
t = t + dxi_ddel*x*y2
1792-
1793-
if sdir == -1 then -- to insure reversal symmetry; horizontal wedge (only sdir) -> PTC uses edir, and if we do this, reversing edir does not give the same result
1794-
px = px + k0hq*x^2
1780+
-- This is still not fully revesible in 4th order, due to dependancy of x on px and vice versa.
1781+
local dpp = 1 + 2/beta*pt + pt^2
1782+
local y2 = y^2
1783+
local _pt2 = 1/(dpp - px^2)
1784+
local xi = 2*k0hq*sqrt(dpp)*_pt2
1785+
local dxi_px = 2*px*xi *_pt2
1786+
1787+
if sdir == -1 then
1788+
local npx = px - xi*y2
1789+
_pt2 = 1/(dpp - npx^2)
1790+
xi = 2*k0hq*sqrt(dpp)*_pt2
1791+
dxi_px = 2*npx*xi *_pt2
1792+
end
1793+
1794+
local dxi_ddel = -2*xi*(1+pt)*_pt2
1795+
1796+
if sdir == 1 then
1797+
x = x / (1-dxi_px*y2)
1798+
px = px - xi*y2
1799+
py = py - 2*xi*x*y
1800+
t = t + dxi_ddel*x*y2
1801+
else
1802+
t = t + dxi_ddel*x*y2
1803+
py = py - 2*xi*x*y
1804+
1805+
x = x / (1-dxi_px*y2)
1806+
px = px - xi*y2 + k0hq*x^2
17951807
end
17961808

17971809
m[i].x = x
@@ -1863,6 +1875,34 @@ function bend_wedge (elm, m, lw_, e) -- [WEDGE] see also [sr]bend_thick --
18631875
m.atdebug(elm, m, 'bend_wedge:1')
18641876
end
18651877

1878+
local function bend_fringe_param (dpp, px, py, c2, b0, tfac, only_ky)
1879+
-- This map could do with some cleaning, use of pz, _pz and _pz2 is inconsistent
1880+
local pz = sqrt(dpp - px^2 - py^2)
1881+
local _pz = 1/pz
1882+
local _pz2 = _pz^2
1883+
1884+
local xp, yp = px/pz, py/pz
1885+
local xyp, yp2 = xp*yp, 1+yp^2
1886+
local xp2,_yp2 = xp^2 , 1/yp2
1887+
1888+
local fi0 = atan((xp*_yp2)) - c2*(1 + xp2*(1+yp2))*pz
1889+
local co2 = b0/cos(fi0)^2
1890+
local co1 = co2/(1 + (xp*_yp2)^2)*_yp2
1891+
local co3 = co2*c2
1892+
1893+
local fi1 = co1 - co3*2*xp*(1+yp2)*pz
1894+
local fi2 = -2*co1*xyp*_yp2 - co3*2*xp*xyp *pz
1895+
local fi3 = - co3*(1 + xp2*(1+yp2))
1896+
1897+
local ky = fi1*xyp*_pz + fi2*yp2*_pz - fi3*yp
1898+
if only_ky then return fi0, nil, ky, nil end -- only ky is needed, speed up calculation
1899+
1900+
local kx = fi1*(1+xp2)*_pz + fi2*xyp*_pz - fi3*xp
1901+
local kz = fi1*tfac*xp*_pz2 + fi2*tfac*yp*_pz2 - fi3*tfac*_pz
1902+
return fi0, kx, ky, kz
1903+
end
1904+
1905+
18661906
function bend_fringe (elm, m, lw) -- [FRINGE_DIPOLE] -- checked
18671907
if abs(m.knl[1]) < minang then return end
18681908
m.atdebug(elm, m, 'bend_fringe:0')
@@ -1884,46 +1924,29 @@ function bend_fringe (elm, m, lw) -- [FRINGE_DIPOLE] --
18841924
local c2 = b0*fh*2
18851925

18861926
local dpp = 1 + 2/beta*pt + pt^2
1887-
local pz = sqrt(dpp - px^2 - py^2)
1888-
local _pz = 1/pz
1889-
local _pz2 = _pz^2
18901927
local relp = invsqrt(dpp)
18911928
local tfac = -(1/beta + pt)
18921929
local c3 = b0^2*fsad*relp
18931930

1894-
local xp, yp = px/pz, py/pz
1895-
local xyp, yp2 = xp*yp, 1+yp^2
1896-
local xp2,_yp2 = xp^2 , 1/yp2
1897-
1898-
local fi0 = atan((xp*_yp2)) - c2*(1 + xp2*(1+yp2))*pz
1899-
local co2 = b0/cos(fi0)^2
1900-
local co1 = co2/(1 + (xp*_yp2)^2)*_yp2
1901-
local co3 = co2*c2
1902-
1903-
local fi1 = co1 - co3*2*xp*(1+yp2)*pz
1904-
local fi2 = -2*co1*xyp*_yp2 - co3*2*xp*xyp *pz
1905-
local fi3 = - co3*(1 + xp2*(1+yp2))
1906-
1907-
local kx = fi1*(1+xp2)*_pz + fi2*xyp*_pz - fi3*xp
1908-
local ky = fi1*xyp*_pz + fi2*yp2*_pz - fi3*yp
1909-
local kz = fi1*tfac*xp*_pz2 + fi2*tfac*yp*_pz2 - fi3*tfac*_pz
1910-
1931+
local fi0, kx, ky, kz = bend_fringe_param(dpp, px, py, c2, b0, tfac, sdir==-1) -- this method is not perfect.
1932+
local ny = 2*y / (1 + sqrt(1-2*ky*y))
19111933
if sdir == 1 then
1912-
y = 2*y / (1 + sqrt(1-2*ky*y))
1913-
local y2 = y^2
1934+
local ny2 = ny^2
19141935

1915-
m[i].x = x + 0.5*kx*y2
1916-
m[i].py = py - (4*c3*y2 + b0*tan(fi0))*y
1917-
m[i].t = t + (0.5*kz + c3*y2*relp^2*tfac)*y2
1918-
m[i].y = y
1936+
m[i].x = x + 0.5*kx*ny2
1937+
m[i].py = py - (4*c3*ny2 + b0*tan(fi0))*ny
1938+
m[i].t = t + (0.5*kz + c3*ny2*relp^2*tfac)*ny2
1939+
m[i].y = ny
19191940
else -- need to reverse y-dependence
1920-
-- This is still not fully revesible in 3rd and 4th order, due to self dependance of y
1941+
-- This is still not fully revesible in 5thand 6th order, due to self dependance of py -> results in max error of 1e-11 and 2e-9 for 5th and 6th order respectively
1942+
local npy = py + (4*c3*ny^2 + b0*tan(fi0))*ny
1943+
fi0, kx, ky, kz = bend_fringe_param(dpp, px, npy, c2, b0, tfac) -- this method is not perfect.
19211944
local y2 = y^2
19221945

19231946
m[i].x = x - 0.5*kx*y2
19241947
m[i].py = py + (4*c3*y2 + b0*tan(fi0))*y
19251948
m[i].t = t - (0.5*kz + c3*y2*relp^2*tfac)*y2
1926-
m[i].y = 0.5*y * (1 + sqrt(1-2*ky*y))
1949+
m[i].y = y - y2*ky/2
19271950
end
19281951
end
19291952

tests/tests/test-ng-maps/test-curved-maps.mad

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,10 @@ function TestCurved:testBENDFACE()
114114
nslice = {1},
115115
energy = {1, 6500}, -- {1, 450, 6500}
116116

117-
tol = 100,
117+
tol = {5, 200, 200, 400, 4e3},--Non zero h2 causes failure at 4th order (h1 is fine for these tolerances)
118118

119-
h1 = {0,-0.04, 0.05},
120-
h2 = {0, 0.04,-0.05},
119+
h1 = {0,-0.04, 0.05}, -- This works with backtracking for tolerances above.
120+
h2 = {0, 0.04,-0.05}, -- This does not work with backtracking at all
121121
alist = tblcat(ref_cfg.alist, {"h1", "h2"}),
122122
plot_info = {
123123
title = "Bend Face NG v NG Maps",

tests/tests/test-ng-maps/test-fringe-maps.mad

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ function TestFringes:testQUADf() -- Test the straight fringes
6969
nslice = {1},
7070
energy = {1, 6500}, -- {1, 450, 6500}
7171

72-
tol = 1e3,
72+
tol = 500, -- bend_fringe will pass backtracking at 480 eps
7373

7474
k1 = {0, -0.15, 0.2},
7575
k1s = {0, -0.15, 0.2},

0 commit comments

Comments
 (0)