Skip to content

Add dipole magnet #136

Open

Description

@JeanLucPons

Implement Dipole magnet.

Today we have only HCorrector and VCorrector.

A dipole is mandatory for ramped machine and/or dipole equipped with an additional correction coil.
Basically a dipole magnet has a model that depends only on $B\rho$.
So the main coil current should change only according to $B\rho$.
This require #90

A correction coil will have a model that will depend on the HCorrector strength and $B\rho$.
Such a Dipole can be configured as:

i.e.

- type: pyaml.magnet.dipole
  name: DIP # All dipoles are named DIP is the lattice
  model:
    type: pyaml.magnet.dipole_linear_model # this model depend only on Brho
    # calibration stuff
    ....
    powerconverter:
      - type: tango.pyaml.attribute
        attribute: srmag/ps-main/dip/current
        unit: A

- type: pyaml.magnet.hcorrector
  name: DIP-C01-H
  lattice_names: DIP@0  # Main current is serialized, we access the good dipole in the lattice
  model:
    type: pyaml.magnet.linear_model # this model depend only on Brho and H strength
    # calibration stuff
    ....
    powerconverter:
      - type: tango.pyaml.attribute
        attribute: srmag/ps-corr-dip/c01/current
        unit: A

- type: pyaml.magnet.hcorrector
  name: DIP-C02-H
  lattice_names: DIP@1  # Main current is serialized, we access the good dipole in the lattice
  model:
    type: pyaml.magnet.linear_model # this model depend on Brho and H strength
    # calibration stuff
    ....
    powerconverter:
      - type: tango.pyaml.attribute
        attribute: srmag/ps-corr-dip/c02/current
        unit: A

Activity

  1. TeresiaOlsson commented on Jan 29, 2026

    @TeresiaOlsson
    Member

    I noticed when testing the orbit correction that the correctors set the dipole component in PolynomB and PolynomA and not KickAngle. Is there a specific reason for that or otherwise maybe when adding the dipole it's worth changing that mapping? I usually use the KickAngle field in pyAT for correctors to be able to easily separate that contribution to potential other things like errors that could also go into the PolynomB and PolynomA.

  2. JeanLucPons commented on Jan 29, 2026

    @JeanLucPons
    MemberAuthor

    Problem of KickAngle is that it is integrated and slightly wrong So in fact it is better to just load PolynomA,B[0] so it stays coherent with other non integrated PolynomA,B coefficients.
    PyAML performs the correction with the length to be in agreement with KL convention.
    However PALS like integrated polynoms has been added in AT recently an can be used.

    In PyAML, if you use corr.angle.set() instead of corr.strength.set() it will perform the tan().

  3. TeresiaOlsson commented on Jan 29, 2026

    @TeresiaOlsson
    Member

    Mhm, I understand. Now I'm wondering what that means for the implementation in pyAML.

    Say that I'm doing simulated commissioning, add some dipole errors and then run orbit correction. When I read the correctors, how does it know how much of the polynom that is corrector strength and how much is from the errors?

    I think if I did that in MML the code wouldn't know and would interpret the whole dipole component as corrector strength because it just reads directly from the lattice object. Does pyAML need some extra layer to keep track of the different contributions? Or perhaps this is something that @kparasch already has a solution for in pySC since I guess the problem is also there?

  4. JeanLucPons commented on Jan 30, 2026

    @JeanLucPons
    MemberAuthor

    IMHO,
    Concerning strength, the best would be to switch to PALS like polynomials.
    Concerning errors, the plan was rather to add something to do something like:
    @simoneliuzzo, tips are welcome ;)

    simulators:
      - type: pyaml.lattice.simulator
        lattice: sr/lattices/ebs.mat
        name: design
      - type: pyaml.lattice.simulator
        lattice: sr/lattices/ebs.mat
        seed: [0x91b7852b8346f561, 0x9827032d829e8e46]
        name: error
    
    # The random number generator will use seed[0] to produce reproductible error set
    
    # Add some coupling, cutoff 2 sigma
    sr.error[0].get_magnets("skews").strengths.add_error( 1e-3 , cutoff=2 )
    # Misalignment
    sr.error[0].get_magnets("quads").position.add_error( [10e-6,10e-6] , cutoff=2 )
    # Multipolar errors
    sr.error[0].get_magnets("quads").strengths.add_multipolar_error( [[1e-10,1e-10],[1e-2,1e-6],[1e-7,1e-7],[1e-7,1e-7], cutoff=2 )
    etc...
    
    # All the above can also be added to the config to produce rings with error out of the box
    
    # Retrieve error
    err = sr.error[0].get_magnets("skews").strengths.get() - sr.design.get_magnets("skews").strengths.get()

    This is just some ideas...

  5. simoneliuzzo commented on Jan 30, 2026

    @simoneliuzzo
    Member

    @JeanLucPons
    I like your use example. It seems rather intuitive to me.
    @kparasch should confirm, but I think also pySC deals internally with the various contributions to corrections.
    also in my commissioning simulations software and in the simulator device server, I only use PolynomA/B.
    The availability in pyAML of various lattices to do actions like:
    err = sr.error[0].get_magnets("skews").strengths.get() - sr.design.get_magnets("skews").strengths.get()
    is the most user friendly and intuitive way to work in my opinon.

  6. kparasch commented on Jan 30, 2026

    @kparasch
    Member

    Indeed pySC is an extra layer between strengths you control and strengths in the simulation.
    It on purpose hides the errors internally so that if you would do something equivalent to:

    design_strengths = sr.design.get_magnets("quads").strengths.get()
    sr.error[0].set_magnets("quads").strengths.set(design_strengths)
    

    You would end up with the same errors as initially generated. This was also the behavior of original SC which makes the simulation feel more close to handling a real accelerator.

    Image

    On the point of KickAngle, I also would prefer just using PolynomB (ideally with PALS convention). For me, having to handle two variables that do the same thing confuses me.

  7. TeresiaOlsson commented on Jan 30, 2026

    @TeresiaOlsson
    Member

    I think sr.error is another part than what I was thinking about. As I understand it that's just the initial lattice model that you load which will have some errors inside but could potentially have zero corrector strength if you haven't already corrected the orbit for that model.

    Then inside pyAML you run the orbit correction and that will set your correctors. Then it sounds like the layer @kparasch says pySC has inside will be needed to know how much is the corrector strength and how much is the error. Otherwise I don't understand how the code would not just read the full value of the polynom, think it's all corrector strength and when you convert into current give a different number than your power supply will actually have.

  8. added this to the ESRF Workshop milestone on Aug 13, 2026
  9. changed the title [-]Feature: Add dipole magnet[/-] [+]Add dipole magnet[/+] on Oct 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions