Skip to content

Commit 6cc2bbf

Browse files
authored
Matching fixes (#615)
* bugfix + phase handling * unstable 4D lattices * remove print and change names * pep8 --------- Co-authored-by: swhite2401 <[email protected]>
1 parent 9bad31d commit 6cc2bbf

File tree

2 files changed

+36
-18
lines changed

2 files changed

+36
-18
lines changed

pyat/at/matching/matching.py

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
"""
22
Classes for matching variables and constraints
33
"""
4+
from __future__ import annotations
45
from itertools import chain
56
import numpy as np
6-
from typing import Optional, Sequence, Callable, Tuple, Union
7+
from collections.abc import Sequence, Callable
8+
from typing import Optional, Union
79
from scipy.optimize import least_squares
810
from itertools import repeat
911
from at.lattice import Lattice, Refpts, bool_refpts
@@ -32,23 +34,23 @@ class Variable(object):
3234
:py:class:`Variable` initialisation
3335
name: Name of the Variable; Default: ``''``
3436
bounds: Lower and upper bounds of the variable value
35-
*args: Positional arguments transmitted to ``setfun`` and
37+
fun_args: Positional arguments transmitted to ``setfun`` and
3638
``getfun`` functions
3739
3840
Keyword Args:
39-
**kwargs: Keyword arguments transmitted to ``setfun``and
41+
**fun_kwargs: Keyword arguments transmitted to ``setfun``and
4042
``getfun`` functions
4143
"""
4244
def __init__(self, setfun: Callable, getfun: Callable,
4345
name: str = '',
44-
bounds: Tuple[float, float] = (-np.inf, np.inf),
45-
*args, **kwargs):
46+
bounds: tuple[float, float] = (-np.inf, np.inf),
47+
fun_args: tuple = (), **fun_kwargs):
4648
self.setfun = setfun
4749
self.getfun = getfun
4850
self.name = name
4951
self.bounds = bounds
50-
self.args = args
51-
self.kwargs = kwargs
52+
self.args = fun_args
53+
self.kwargs = fun_kwargs
5254
super(Variable, self).__init__()
5355

5456
def set(self, ring: Lattice, value):
@@ -90,7 +92,7 @@ class ElementVariable(Variable):
9092
def __init__(self, refpts: Refpts, attname: str,
9193
index: Optional[int] = None,
9294
name: str = '',
93-
bounds: Tuple[float, float] = (-np.inf, np.inf)):
95+
bounds: tuple[float, float] = (-np.inf, np.inf)):
9496
setf, getf = self._access(index)
9597

9698
def setfun(ring, value):
@@ -357,7 +359,8 @@ class LinoptConstraints(ElementConstraints):
357359
transfer matrix. Can be :py:obj:`~.linear.linopt2`,
358360
:py:obj:`~.linear.linopt4`, :py:obj:`~.linear.linopt6`
359361
360-
* :py:obj:`~.linear.linopt2`: No longitudinal motion, no H/V coupling,
362+
* :py:obj:`~.linear.linopt2`: No longitudinal motion,
363+
no H/V coupling,
361364
* :py:obj:`~.linear.linopt4`: No longitudinal motion, Sagan/Rubin
362365
4D-analysis of coupled motion,
363366
* :py:obj:`~.linear.linopt6` (default): With or without longitudinal
@@ -369,7 +372,8 @@ class LinoptConstraints(ElementConstraints):
369372
370373
Add a beta x (beta[0]) constraint at location ref_inj:
371374
372-
>>> cnstrs.add('beta', 18.0, refpts=ref_inj, name='beta_x_inj', index=0)
375+
>>> cnstrs.add('beta', 18.0, refpts=ref_inj,
376+
name='beta_x_inj', index=0)
373377
374378
Add an horizontal tune (tunes[0]) constraint:
375379
@@ -435,6 +439,7 @@ def add(self, param, target, refpts: Optional[Refpts] = None,
435439
getf = self._recordaccess(index)
436440
getv = self._arrayaccess(index)
437441
use_integer = kwargs.pop('UseInteger', False)
442+
norm_mu = {'mu': 1, 'mun': 2*np.pi}
438443

439444
if name is None: # Generate the constraint name
440445
name = param.__name__ if callable(param) else param
@@ -444,7 +449,6 @@ def add(self, param, target, refpts: Optional[Refpts] = None,
444449
if callable(param):
445450
def fun(refdata, tune, chrom):
446451
return getv(param(refdata, tune, chrom))
447-
# self.refpts[:] = True # necessary not to miss 2*pi jumps
448452
self.get_chrom = True # fun may use dispersion or chroma
449453
elif param == 'tunes':
450454
# noinspection PyUnusedLocal
@@ -457,14 +461,20 @@ def fun(refdata, tune, chrom):
457461
return getv(chrom)
458462
refpts = []
459463
self.get_chrom = True # slower but necessary
464+
elif param == 'mu' or param == 'mun':
465+
# noinspection PyUnusedLocal
466+
def fun(refdata, tune, chrom):
467+
if use_integer:
468+
return getf(refdata, 'mu') / norm_mu[param]
469+
else:
470+
return (getf(refdata, 'mu') % (2*np.pi)) / norm_mu[param]
471+
if use_integer:
472+
self.refpts[:] = True # necessary not to miss 2*pi jumps
473+
else:
474+
target = target % (2 * np.pi / norm_mu[param])
460475
else:
461476
# noinspection PyUnusedLocal
462477
def fun(refdata, tune, chrom):
463-
if param == 'mu':
464-
return getf(refdata, param) % (2*np.pi)
465-
elif param == 'mu' and use_integer:
466-
# necessary not to miss 2*pi jumps
467-
self.refpts[:] = True
468478
return getf(refdata, param)
469479

470480
super(LinoptConstraints, self).add(fun, target, refpts, name=name,

pyat/at/physics/linear.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from ..constants import clight
1111
from ..lattice import DConstant, Refpts, get_bool_index, get_uint32_index
1212
from ..lattice import AtWarning, Lattice, Orbit, check_6d, get_s_pos
13+
from ..lattice import AtError
1314
from ..lattice import frequency_control
1415
from ..tracking import lattice_pass
1516
from .orbit import find_orbit4, find_orbit6
@@ -89,11 +90,18 @@ def _closure(m22):
8990
def _tunes(ring, **kwargs):
9091
""""""
9192
if ring.is_6d:
93+
nd = 3
9294
mt, _ = find_m66(ring, **kwargs)
9395
else:
96+
nd = 2
9497
mt, _ = find_m44(ring, **kwargs)
95-
_, vps = a_matrix(mt)
96-
tunes = numpy.mod(numpy.angle(vps) / 2.0 / pi, 1.0)
98+
try:
99+
_, vps = a_matrix(mt)
100+
tunes = numpy.mod(numpy.angle(vps) / 2.0 / pi, 1.0)
101+
except AtError:
102+
warnings.warn(AtWarning('Unstable ring'))
103+
tunes = numpy.empty(nd)
104+
tunes[:] = numpy.NaN
97105
return tunes
98106

99107

0 commit comments

Comments
 (0)