Skip to content

Beam tracing dependency order re-factoring

finesse importer requested to merge refactor/traceorder into master

Inspired by #203 (closed) --- i.e. changes to the parser which mean that commands are not guaranteed to be parsed in the order in which they appear in the kat file; leading to the need for a more robust, well-defined and stable way to order tracing dependencies (i.e. Cavities and Gausses).

The following is copied from my first comment on the issue linked above...

traceorder command (and associated Model attribute)

This command would define the order in which dependencies will be traced in the model. Note that internal cavity traces (i.e setting the eigenmode and qs at nodes internal to the cavity) will always come first.

Simplest case --- no traceorder required as only one cav

l L0 P=1

s s0 L0.p1 ITM.p1

m ITM R=0.99 T=0.01 Rc=-10
s CAV ITM.p2 ETM.p1 L=1
m ETM R=0.99 T=0.01 Rc=10

cav FP ITM.p2

Here no traceorder is required as the only dependency is FP. The trace forest constructing algorithm knows this info, so fine to continue.

Another simple case --- no traceorder reqd as one cav and one gauss

l L0 P=1

s s0 L0.p1 BS.p1

bs BS

s s1 BS.p3 ITM.p1

m ITM R=0.99 T=0.01 Rc=-10
s CAV ITM.p2 ETM.p1 L=1
m ETM R=0.99 T=0.01 Rc=10

gauss gL0 L0.p1.o z=-0.5 w0=1m
cav FP ITM.p2

Traces from cavities are executed before traces from manual qs (behaviour used by Finesse 2) so again no traceorder needed here as FP external trace will take place before gL0 trace.

In this case the trace results would be:

Internal trace of cavity: FP (q = -0.50 + 2.18j, g = 0.81)

    o ITM.p2.o: [q = -0.50 + 2.18j]
    ╰──o ETM.p1.i: [q = 0.50 + 2.18j]
       ╰──o ETM.p1.o: [q = -0.50 + 2.18j]
          ╰──o ITM.p2.i: [q = 0.50 + 2.18j]

Dependency: FP

    o ETM.p1.i: [q = 0.50 + 2.18j]
    ╰──o ETM.p2.o: [q = 0.50 + 2.18j]

Dependency: FP

    o ITM.p2.i: [q = 0.50 + 2.18j]
    ╰──o ITM.p1.o: [q = 0.50 + 2.18j]
       ╰──o BS.p3.i: [q = 0.50 + 2.18j]
          ╰──o BS.p4.o: [q = 0.50 + 2.18j]

Dependency: gL0

    o L0.p1.o: [q = -0.50 + 2.95j]
    ╰──o BS.p1.i: [q = -0.50 + 2.95j]
       ╰──o BS.p2.o: [q = -0.50 + 2.95j]

Whilst traceorder is not required in this case, it could be used to modify the behaviour here; i.e:

l L0 P=1

s s0 L0.p1 BS.p1

bs BS

s s1 BS.p3 ITM.p1

m ITM R=0.99 T=0.01 Rc=-10
s CAV ITM.p2 ETM.p1 L=1
m ETM R=0.99 T=0.01 Rc=10

gauss gL0 L0.p1.o z=-0.5 w0=1m
cav FP ITM.p2

traceorder gL0 FP

so now gL0 trace gets performed before trace from FP, leading to these trace data:

Internal trace of cavity: FP (q = -0.50 + 2.18j, g = 0.81)

    o ITM.p2.o: [q = -0.50 + 2.18j]
    ╰──o ETM.p1.i: [q = 0.50 + 2.18j]
       ╰──o ETM.p1.o: [q = -0.50 + 2.18j]
          ╰──o ITM.p2.i: [q = 0.50 + 2.18j]

Dependency: gL0

    o L0.p1.o: [q = -0.50 + 2.95j]
    ╰──o BS.p1.i: [q = -0.50 + 2.95j]
       ├──o BS.p2.o: [q = -0.50 + 2.95j]
       ╰──o BS.p3.o: [q = -0.50 + 2.95j]
          ╰──o ITM.p1.i: [q = -0.50 + 2.95j]

Dependency: FP

    o ETM.p1.i: [q = 0.50 + 2.18j]
    ╰──o ETM.p2.o: [q = 0.50 + 2.18j]

Dependency: gL0

    o BS.p3.i: [q = 0.50 + 2.95j]
    ╰──o BS.p4.o: [q = 0.50 + 2.95j]

Multiple cav commands --- traceorder required

l L0 P=1

s s0 L0.p1 BS.p1

bs BS

s sX BS.p3 ITMX.p1

m ITMX R=0.99 T=0.01 Rc=-10
s LX ITMX.p2 ETMX.p1 L=1
m ETMX R=0.99 T=0.01 Rc=10

s sY BS.p2 ITMY.p1

m ITMY R=0.99 T=0.01 Rc=-10
s LY ITMY.p2 ETMY.p1 L=1
m ETMY R=0.99 T=0.01 Rc=10

cav FPX ITMX.p2
cav FPY ITMY.p2

traceorder FPX FPY

Now traceorder must be defined as have multiple cav commands. If it is not given then the beam tracing would raise an error.

The same situation would exist for a model with multiple gauss commands.

How would traceorder be implemented from the Model perspective?

  • Initialise a traceorder list in the Model from the args given via kat-file syntax.

If no traceorder is given (as it's not required for simple cases, see earlier) then it will automatically be set as (pseudo-code):

self.traceorder = [sole cavity (if it exists), sole gauss (if it exists)]

For running beam traces on a model:

  • Model.beam_trace would then use this list to construct the trace_forest
  • except for in the case when the order arg is given to this call (i.e. allowing temporary overriding of the order for a specific beam trace call)
  • also the disable and enable_only args of beam_trace would still exist and work the same as now.

When constructing the trace forest for a simulation:

  • The "order" arg in Model.beam_trace_args would be set to Model.traceorder so that the trace_forest constructed during the simulation initialisation will correspond to this order.
  • But this could again be temporarily overridden for a given simulation in a (pretty much) identical way to now by setting Model.beam_trace_args["order"] = some_other_order_sequence.

What about via Python API?

If Cavity objects are added to the Model via Python, then there are couple of options:

  1. Enforce that Model.traceorder be set after adding multiple cavities or gausses.

  2. Enforce that any call to Model.beam_trace must specify the (existing) order arg when there are multiple cavities and / or gausses. This wouldn't be so nice though as then the various trace-tool functions (like propagate_beam) would require order to be passed via the **kwargs to beam_trace when q_in not given.

  3. Explicitly take into account that we are not in a "parsing state" and so set Model.traceorder automatically to the order in which cavities and gauss objects are added to the Model (i.e. essentially current behaviour).

Edited by finesse importer

Merge request reports