Skip to content

Feature: Refactor element attachment using holder-specific dispatch #361

Description

@gupichon

Description, motivation and use case

Simulator.fill_device() and ControlSystem.fill_device() currently contain long if/elif chains that dispatch behaviour based on the concrete element type.
This makes the attachment logic harder to extend: adding a new element type requires modifying every ElementHolder implementation, while the element definition itself does not express how it should be attached.

The goal is to introduce a clearer dispatch mechanism in preparation for future device types. Element definitions will select the relevant holder operation, while each holder remains responsible for creating its own concrete runtime objects (simulation read-writers, control-system device access, etc.).

Proposed solution

This issue only covers the first refactoring step. It will preserve the current behaviour while separating dispatch from holder-specific implementation details.
ElementHolder.fill_device() will iterate over the configured elements and delegate the attachment to each element. Each element type will implement a fill_device(holder) method and call the appropriate holder-specific method. Concrete holders, such as Simulator and ControlSystem, will implement these methods.

This keeps runtime-specific logic in the holder and removes the central type-dispatch chains.

Alternatives considered

Keep the current if/elif chains.

This would keep the implementation simple in the short term, but every new element type would require changes to all holder implementations and would make the attachment code increasingly difficult to maintain.

Example

The following pseudo-code illustrates the intended double-dispatch mechanism:

class CombinedFunctionMagnet(Element, DynamicValidation):
    def fill_device(self, holder: ElementHolder) -> None:
        holder.fill_combined_function_magnet(self)


class ElementHolder:
    def fill_device(self, elements: list[Element]) -> None:
        for element in elements:
            element.fill_device(self)


class Simulator(ElementHolder):
    def fill_combined_function_magnet(
        self, element: CombinedFunctionMagnet
    ) -> None:
        currents = (
            RWHardwareArray(
                self.get_at_elems(element),
                element.polynoms,
                element.model,
            )
            if element.model.has_physics()
            else None
        )
        strengths = (
            RWStrengthArray(
                self.get_at_elems(element),
                element.polynoms,
                element.model,
            )
            if element.model.has_physics()
            else None
        )

        magnets = element.attach(self, strengths, currents)
        self.combined_function_magnet.add(magnets[0])
        for magnet in magnets[1:]:
            self.magnet.add(magnet)

Additional context

The refactoring must preserve the current attachment behaviour for magnets, combined-function magnets, serialized magnets, BPMs, RF plants, tune monitors, tools, and unbound elements.

No new device type or change to the public configuration format is included in this issue.

Checklist

  • I've assigned this issue to a project
  • I've @-mentioned relevant people

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions