Beam tracing dependency order re-factoring
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.
traceorder
required as only one cav
Simplest case --- no 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.
traceorder
reqd as one cav
and one gauss
Another simple case --- no 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]
cav
commands --- traceorder
required
Multiple 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.
traceorder
be implemented from the Model perspective?
How would - Initialise a
traceorder
list in theModel
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 thetrace_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
andenable_only
args ofbeam_trace
would still exist and work the same as now.
When constructing the trace forest for a simulation:
- The
"order"
arg inModel.beam_trace_args
would be set toModel.traceorder
so that thetrace_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:
-
Enforce that
Model.traceorder
be set after adding multiple cavities or gausses. -
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 (likepropagate_beam
) would requireorder
to be passed via the**kwargs
tobeam_trace
whenq_in
not given. -
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).