MUSCLE3 IMAS Actor

The waveform editor includes an actor that can be included in an IMAS MUSCLE3 simulation. This page assumes you are familiar with MUSCLE3 and IMAS coupled simulations.

Caution

The IMAS MUSCLE3 actor requires the following packages:

Actor details

The actor expects a message on a single input port, evaluates all configured waveforms, and sends each resulting IDS on its matching (connected) output port. The name of the input port selects between two modes:

  • Fresh export -- when the port name is not an IDS name (e.g. time_in). The waveforms are evaluated at the message timestamp into a single new time slice per output IDS. Only the timestamp of the incoming message is used.

  • Overlay -- when the port name is <ids>_in (or <ids>, i.e. a valid IDS name). The message must carry that IDS; the actor reads its time array, evaluates the waveforms on every time present, and overlays them onto the received IDS in place -- preserving all of its other data -- before sending it on. This lets the actor sit inline in a pipeline and augment an IDS passing through, for example adding a plasma-current waveform to an equilibrium on its way to a solver, rather than emitting a fresh IDS. The actor stops with a RuntimeError if such a port receives no IDS, or an IDS whose time array is empty.

Example implementations section for running the waveform-editor actor
implementations:
  waveform_actor:
    executable: waveform-editor
    args: actor

Available settings

  • waveforms (mandatory): indicate the (full) path to the waveform configuration.

Input ports (F_INIT)

The actor has exactly one input port, whose name selects the export mode (see Actor details): name it <ids>_in (or <ids>) for overlay mode -- the time base is read from, and the waveforms overlaid onto, the IDS carried in the message; use any other name (e.g. time_in) for fresh export at the message timestamp.

The actor will stop with a RuntimeError when there are no input ports, or when there are multiple input ports declared.

Output ports (O_F)

The actor can have one output port per IDS that is defined in the waveform configuration. Output ports must be named <ids_name>_out or <ids_name>.

The actor will stop with a RuntimeError when an output port is connected for which there is no corresponding waveform defined. For below example, the actor would report an error when the waveforms.yaml doesn't contain waveforms for either the ec_launchers IDS or the nbi IDS.

Example: fresh export

The following yMMSL shows an example coupling for a hypothetical controller actor with the waveform-editor actor. The actor's input port is time_in (not an IDS name), so it runs in fresh export mode: the controller drives it with timestamps and gets back a single-slice ec_launchers and nbi IDS each step. N.B. __PATH__ is a placeholder which should be replaced with the full path to the files.

coupling.ymmsl.in
ymmsl_version: v0.1

model:
  name: example_coupling_with_waveform_actor

  components:
    controller:
      implementation: controller
      ports:
        o_i: time_out
        s:
        - ec_launchers_in
        - nbi_in
      
    waveform_actor:
      implementation: waveform_actor
      ports:
        # The name of the input port can be freely chosen:
        f_init: time_in
        # Names of the output port are "<ids_name>_out":
        o_f:
        - ec_launchers_out
        - nbi_out
    
  conduits:
    controller.time_out: waveform_actor.time_in
    waveform_actor.ec_launchers_out: controller.ec_launchers_in
    waveform_actor.nbi_out: controller.nbi_in

settings:
  # Mandatory setting for the waveform actor: the waveform configuration:
  waveform_actor.waveforms: __PATH__/waveforms.yaml

resources:
  controller:
    threads: 1
  waveform_actor:
    threads: 1

implementations:
  controller:
    executable: python
    args: __PATH__/controller.py
  
  waveform_actor:
    executable: waveform-editor
    args: actor

The corresponding waveform configuration is shown below:

waveforms.yaml
# Very simple waveform configuration as an example for the MUSCLE3 IMAS actor
globals:
  dd_version: 4.0.0

ec_launchers:
  ec_launchers/beam(1)/power_launched/data:
    # Ramp up to 50 kW
    - {type: linear, to: 50e3, duration: 10}
    # Flat top, constant at 50 kW
    - {type: constant, duration: 30}
    # Ramp down
    - {type: linear, to: 0, duration: 10}

nbi:
  # Note that the actor would give an error if we do not include this waveform:
  # the yMMSL file expects an output for the NBI IDS, so we must define
  # waveforms for this IDS.
  nbi/unit(1)/power_launched/data:
  - {type: constant, value: 0}  # NBI is turned off for this configuration

Example: overlay

In overlay mode the actor augments an IDS that flows through it. Below, a hypothetical solver sends an equilibrium to the actor and receives it back with the configured waveforms (here the plasma current ip) written onto every time slice; all other equilibrium data is preserved. The input port equilibrium_in is what selects overlay mode. N.B. __PATH__ is a placeholder which should be replaced with the full path to the files.

overlay.ymmsl.in
ymmsl_version: v0.1

model:
  name: example_overlay_with_waveform_actor

  components:
    solver:
      implementation: solver
      ports:
        o_i: equilibrium_out
        s:
        - equilibrium_in

    waveform_actor:
      implementation: waveform_actor
      ports:
        # An IDS-named input port exposes the received IDS as a port-import:
        f_init: equilibrium_in
        # Name of the output port is "<ids_name>_out":
        o_f:
        - equilibrium_out

  conduits:
    solver.equilibrium_out: waveform_actor.equilibrium_in
    waveform_actor.equilibrium_out: solver.equilibrium_in

settings:
  # Mandatory setting for the waveform actor: the waveform configuration:
  waveform_actor.waveforms: __PATH__/overlay_waveforms.yaml

resources:
  solver:
    threads: 1
  waveform_actor:
    threads: 1

implementations:
  solver:
    executable: python
    args: __PATH__/overlay_solver.py

  waveform_actor:
    executable: waveform-editor
    args: actor

The corresponding waveform configuration is shown below:

overlay_waveforms.yaml
# Waveform configuration for the overlay example: the equilibrium received on the
# 'equilibrium_in' port is imported whole (overlay base), then a single plasma-current
# ramp is written onto every time slice while its other data (the boundary) is kept.
globals:
  dd_version: 4.0.0
  imports:
    eq_in: {port: equilibrium_in}

Plasma current:
  equilibrium/*:
    - {ref: eq_in}
  equilibrium/time_slice/global_quantities/ip:
    - {type: linear, to: -15e6, duration: 100}

Last update: 2026-07-16