The ‘frequency_response’ action for modelling transfer functions¶
As seen in the previous section we can manually compute single input to multiple output (SIMO) transfer functions with a few lines of KatScript. If we wanted to inject multiple signals separately from one another to compute a full multiple input multiple output (MIMO) it can get awkward with the manual method. This would require adding and removing signal generators in some for-loop then concatenating all the results together.
In Finesse 3 we have introduced the Readout
component. This is a mix of a detector
and a component. it has one optical port for light to be incident on, then it can have
one or several output electrical ports. This means instead of taking transfer functions
from some signal generator to a detector, we can simple take specify electrical or
mechanical nodes to inject a signal at, then simply read the result out at another node.
Consider a similar example to what we discussed in the previous section: a laser beam
reflected from a mirror far away then back on to a photodiode. Instead of specifying a
power detector pd1
we now use a readout_dc
component which we’ll call REFL
.
This models a photodiode which measures signal fluctuations and converts it into an
electrical output at the port REFL.DC
. You’ll notice in this we do not need to
specify the signal frequency like we did previously with pd1
import finesse
finesse.init_plotting()
model = finesse.Model()
model.parse("""
l l1 P=1
s s1 l1.p1 m1.p1 L=10k
m m1 R=1 T=0
readout_dc REFL l1.p1.i
butter current_drive 1 lowpass 5k
link(current_drive, l1.amp)
fsig(1)
""")
Now we introduce a new analysis that can be performed on a model, the
frequency_response
action. This single action allows you to inject multiple signals
and read them out at multiple outputs over a generic frequency vector. Above we use the
geomspace(start, stop, steps)
(:seealso: numpy.geomspace
) to create a
logarithmic vector (linspace
is also available as well as specify arbitrary ones,
e.g. [1, 10, 11.5, 18]
). Next we provide an array of inputs nodes, followed by an
array (or singular in this case) output node.
model.parse("""
frequency_response(
geomspace(100, 100k, 100), # frequency vector
[current_drive.p1.i, l1.amp.i], # injection nodes
REFL.DC.o # output nodes
)
""")
sol = model.run()
sol.plot();
<Figure size 576x355.968 with 0 Axes>
sol.plot_readouts(); # alternate plot method
Note
In cases where a port only has a single node you can just write the port for
shorthand REFL.DC.o
is equivalent to REFL.DC
when some element or command
expects a node.