Example 1 - simple cavity

The best way to familiarise yourself with Finesse is with example models. In this section we will cover the simple case of modelling resonances in a Fabry-Perot cavity as a starting point.

The optical configuration

In the figure below we show the layout that we want to model. This consists of an input laser incident upon a two-mirror optical cavity. Measuring the reflected, transmitted and circulating power requires the use of three photodiodes - PDrefl, PDtrans and PDcirc, respectively.

../../_images/fabry_perot_example1.svg

To find the resonances of this cavity we can either change the tuning(s) of the mirrors or scan over the frequency of the input laser. In this case we will alter the tuning of the input mirror m1 in the range \(\phi_{\mathrm{m1}} \in [-180^{\circ}, 180^{\circ}]\) to show multiple (repeated) resonances.

The Finesse model

To represent the above layout with a Finesse model we can write the following Python code:

import finesse
finesse.configure(plotting=True)

kat = finesse.Model()
kat.parse(
    """
    # Add a Laser named L0 with a power of 1 W.
    l L0 P=1

    # Space attaching L0 <-> m1 with length of 0 m (default).
    s s0 L0.p1 m1.p1

    # Input mirror of cavity.
    m m1 R=0.99 T=0.01

    # Intra-cavity space with length of 1 m.
    s CAV m1.p2 m2.p1 L=1

    # End mirror of cavity.
    m m2 R=0.991 T=0.009

    # Power detectors on reflection, circulation and transmission.
    pd refl m1.p1.o
    pd circ m2.p1.i
    pd trns m2.p2.o

    # Scan over the detuning DOF of m1 from -180 deg to +180 deg with 400 points.
    xaxis(m1.phi, lin, -180, 180, 400)
    """
)

Firstly, we call configure() with plotting=True. This sets up some defaults for plotting styles, such as line colours and font size. Next, we create a new Model, and then parse our KatScript (see KatScript for more details on the syntax used). This creates a model of a Fabry-Perot cavity with a length of 1 metre and nerly equal reflectivities on both the input mirror and end mirror. The input laser power is set to 1 W.

The last line isn’t part of the model, but defines an Action that will operate on the model. In this case it is an Xaxis, which sweeps some parameter of the model between two limits. For more details on actions and analyses, see the analyses introduction.

Plotting the outputs

To run this model and plot the outputs from the power-detectors we can simply write:

out = kat.run()
out.plot(logy=True);
../../_images/1_simple_cav_1_0.svg

The call to run() causes the Xaxis we defined before to run on the model. This returns an ArraySolution, containing the output of each detector at each point on the axis. We then plot the detector outputs, via plot(). The logy flag tells the plotting routines to use a log-scale on the y-axis of any produced figures.

Printing model information

There are three options for outputting a textual summary of the model. Firstly, printing the model directly gives the usual Python object information:

print(kat)
<finesse.model.Model object at 0x7f23406ed310>

Secondly, you can output a tree view of the nodal network with components as nodes and connected components as branches. Such a tree can be printed in the following way:

print(kat.component_tree(kat.L0))
○ L0
╰──○ m1
   ╰──○ m2

The argument to component_tree() is the component to start from (the tree’s root). Any component in the model can be the tree root.

Note

Models that contain cyclic connections (such as Sagnac interferometers) will not show one of the connections that would create the cycle, to prevent infinite recursion.

Lastly, the most verbose option is to unparse() the model. This returns KatScript which can be used to recreate the model.

print(kat.unparse())
laser L0 P=1.0 f=0.0 phase=0.0
mirror m1 R=0.99 T=0.01 L=0.0 phi=0.0 Rc=[inf, inf] xbeta=0.0 ybeta=0.0 misaligned=false
space s0 portA=L0.p1 portB=m1.p1 L=0.0 nr=1.0 gouy_x=0.0 gouy_y=0.0
mirror m2 R=0.991 T=0.009 L=0.0 phi=0.0 Rc=[inf, inf] xbeta=0.0 ybeta=0.0 misaligned=false
space CAV portA=m1.p2 portB=m2.p1 L=1.0 nr=1.0 gouy_x=0.0 gouy_y=0.0
power_detector_dc refl node=m1.p1.o pdtype=none
power_detector_dc circ node=m2.p1.i pdtype=none
power_detector_dc trns node=m2.p2.o pdtype=none
lambda(1.064e-06)
xaxis(parameter=0.0, mode=lin, start=-180, stop=180, steps=400, relative=false, pre_step=none, post_step=none, name='xaxis')