Source code for pyaml.magnet.cfm_magnet

from scipy.constants import speed_of_light

from ..common import abstract
from ..common.abstract import RWMapper
from ..common.element import Element, ElementConfigModel, __pyaml_repr__
from ..common.exception import PyAMLException
from ..configuration.factory import ELEMENT_REGISTRY
from .hcorrector import HCorrector
from .magnet import Magnet, MagnetConfigModel
from .model import MagnetModel
from .octupole import Octupole
from .quadrupole import Quadrupole
from .sextupole import Sextupole
from .skewoctu import SkewOctu
from .skewquad import SkewQuad
from .skewsext import SkewSext
from .vcorrector import VCorrector

_fmap: dict = {
    "B0": HCorrector,
    "A0": VCorrector,
    "B1": Quadrupole,
    "A1": SkewQuad,
    "B2": Sextupole,
    "A2": SkewSext,
    "B3": Octupole,
    "A3": SkewOctu,
}

# Define the main class name for this module
PYAMLCLASS = "CombinedFunctionMagnet"


[docs] class ConfigModel(ElementConfigModel): mapping: list[list[str]] """Name mapping for multipoles (i.e. [[B0,C01A-H],[A0,C01A-H],[B2,C01A-S]])""" model: MagnetModel | None = None """Object in charge of converting magnet strenghts to currents"""
[docs] class CombinedFunctionMagnet(Element): """CombinedFunctionMagnet class""" def __init__(self, cfg: ConfigModel, peer=None): super().__init__(cfg.name) self._cfg = cfg self.model = cfg.model self.__virtuals: list[Magnet] = [] self.__strengths: abstract.ReadWriteFloatArray = None self.__hardwares: abstract.ReadWriteFloatArray = None if peer is None: # Configuration part if self.model is not None and not hasattr(self.model._cfg, "multipoles"): raise PyAMLException(f"{cfg.name} model: mutipolesfield required for combined function magnet") idx = 0 self.polynoms = [] for _idx, m in enumerate(cfg.mapping): # Check mapping validity if len(m) != 2: raise PyAMLException("Invalid CombinedFunctionMagnet mapping for {m}") if m[0] not in _fmap: raise PyAMLException(m[0] + " not implemented for combined function magnet") if m[0] not in self.model._cfg.multipoles: raise PyAMLException(m[0] + " not found in underlying magnet model") self.polynoms.append(_fmap[m[0]].polynom) # Create the virtual magnet for the correspoding multipole vm = self.__create_virutal_manget(m[1], m[0]) self.__virtuals.append(vm) # Register the virtual element in the factory to have # a coherent factory and improve error reporting ELEMENT_REGISTRY.register(vm) else: # Attach self._peer = peer
[docs] def get_model_name(self) -> str: """ Returns the model name of this magnet """ return self._cfg.name
def __create_virutal_manget(self, name: str, idx: int) -> Magnet: args = {"name": name, "model": self.model} mVirtual: Magnet = _fmap[idx](MagnetConfigModel(**args)) mVirtual.set_model_name(self.get_name()) return mVirtual
[docs] def nb_multipole(self) -> int: return len(self._cfg.mapping)
[docs] def attach( self, peer, strengths: abstract.ReadWriteFloatArray, hardwares: abstract.ReadWriteFloatArray, ) -> list[Magnet]: l = [] # Attached the CombinedFunctionMagnet itself nCFM = CombinedFunctionMagnet(self._cfg, peer) nCFM.__strengths = strengths nCFM.__hardwares = hardwares l.append(nCFM) # Construct a single function magnet for each multipole # of this combined function magnet for idx, _m in enumerate(self._cfg.mapping): strength = RWMapper(strengths, idx) hardware = RWMapper(hardwares, idx) if self.model.has_hardware() else None l.append(self.__virtuals[idx].attach(peer, strength, hardware)) return l
@property def strengths(self) -> abstract.ReadWriteFloatScalar: """ Gives access to the strengths of this combined function magnet in physics unit """ self.check_peer() if self.__strengths is None: raise PyAMLException(f"{str(self)} has no model that supports physics units") return self.__strengths @property def hardwares(self) -> abstract.ReadWriteFloatScalar: """ Gives access to the strengths of this combined function magnet in hardware unit when possible """ self.check_peer() if self.__hardwares is None: raise PyAMLException(f"{str(self)} has no model that supports hardware units") return self.__hardwares
[docs] def set_energy(self, E: float): if self.model is not None: self.model.set_magnet_rigidity(E / speed_of_light)
def __repr__(self): return __pyaml_repr__(self)