Phase configuration settings

Warning

Use the phase 0 or phase 2 option, which can be set with model.phase_config(zero_k00=False, zero_tem00_gouy=False) or model.phase_config(zero_k00=False, zero_tem00_gouy=True), for physically correct results.

Note

Since version 3.0a28 the default phase setting is now model.phase_config(zero_k00=False, zero_tem00_gouy=True).

The phase command can be used to switch on/off some simplifications when dealing with the phase of the light field. This is to aid in simulating systems more easily.

In previous versions of Finesse this was known as the phase command. It was a bitflag setting that switched two options for running simple simulations quickly without having to set up a sensing and control scheme - which was laborious in previous versions of Finesse. With the new actions available in Finesse 3 you can more easily put optical systems at sensible operating points, therefore these phase options are less useful as files are not tuned by hand to be at a particular operating point.

These options were referred to in previous versions of Finesse as:

  • phase 0: No simplification. This means for example that the Gouy phase of a TEM00 is not zero and thus a space of arbitrary length is in general not resonant to the carrier field

  • phase 1: The phase of coupling coefficients is shifted such that the phase of k00 is 0. The phases of all coupling coefficients knm for one field coupling, for example, a reflection at one side of a mirror, are changed by the same amount. To some effect that resembles the movement of the optical surface. However, since this is independently applied to all coupling coefficients of the surface (e.g. two reflections and two transmissions), this does not describe a physically realistic situation. In fact, it might invalidate energy conservation or produce other weird effects.

  • phase 2: The phase accumulated in a space component is adjusted such that the phase of TEM00 set to 0. This simply removes the effect from the Gouy phase on the resonance of the space components, i.e. the length of a space is made to no longer be an integer multiple of the wavelength in order to produce the desired effect of resonance for the TEM00 mode.

  • phase 3: Both of the above (1+2)

In Finesse 3 these are now set using the finesse.model.Model.phase_config(). This accepts keyword arguments which are easier to remember than the bitflag input:

  • phase 3 == zero_k00=True, zero_tem00_gouy=True

  • phase 2 == zero_k00=False, zero_tem00_gouy=True

  • phase 1 == zero_k00=True, zero_tem00_gouy=False

  • phase 0 == zero_k00=False, zero_tem00_gouy=False

Users performing complex simulations should ensure they only use zero_k00=False. This will mean that the numerical value for tuning optic positions for obvious operating points will not apply. For example, resonating a Fabry-Perot cavity for HG00 with phase 3 will use mirrors with phi=0, this is not likely to be the case with phase 2 or phase 0. In such cases, always ensure you use some locking routine or optimiser to find the correct operating point.

Removing the TEM00 Gouy phase: phase 2

Removing the Gouy phase using the zero_tem00_gouy=True does not have a detrimental effect on the accuracy of the simulations. Using this flag will ensure that the HG00 mode when propagating along a space will accumulate no Gouy phase, physically this is like every space is tuned microscopically to remove this. The following example shows how the resonance condition of a cavity is shifted when the Gouy phase is not zeroed.

import finesse
import matplotlib.pyplot as plt

finesse.init_plotting()

model = finesse.script.parse(
    """
    laser l1
    m m1 R=0.99 T=0.01 Rc=100
    m m2 R=0.99 T=0.01 Rc=100
    link(l1, m1.p2, m1.p1, 80, m2.p1)
    cav cavity m1.p1.o
    pd CIRC m1.p1.o
    modes(even, maxtem=10)
    """
)

model.beam_trace()

q_mismatch = finesse.BeamParam.overlap_contour(model.l1.p1.o.q, 0.1, 0)
model.l1.p1.o.q = q_mismatch

action = 'xaxis(m2.phi, lin, -180, 180, 1000, True, name="xaxis")'

labels = [f"phase {i}" for i in range(4)]
lss = ["-", "--", "-", "--"]
model.phase_config(zero_k00=False, zero_tem00_gouy=False)
out0 = model.run(action)
model.phase_config(zero_k00=True, zero_tem00_gouy=False)
out1 = model.run(action)
model.phase_config(zero_k00=False, zero_tem00_gouy=True)
out2 = model.run(action)
model.phase_config(zero_k00=True, zero_tem00_gouy=True)
out3 = model.run(action)


for out, lbl, ls in zip([out0, out1, out2, out3], labels, lss):
    plt.semilogy(out.x[0], out["CIRC"], ls=ls, label=lbl)

plt.legend()
plt.xlabel("End mirror tuning [deg]")
plt.ylabel("Power [W]")
plt.title("Circulating power vs phase configuration")
Text(0.5, 1.0, 'Circulating power vs phase configuration')
../../_images/phase_configurations_0_1.svg

Example of errors zeroing scattering matrix TEM00 coupling: phase 1

Below is an example where using zero_k00=True causes an unwanted error in the calculations. The example is a mode mismatched Fabry-Perot cavity. It demonstrates how using zero_k00=True returns an incorrect reflected field and total power in the simulation is no longer conserved. The pseudo_lock_cavity action is used to easily find the correct operating point in each case to compare the scenarios fairly.

model = finesse.script.parse(
    """
    laser l1
    m m1 R=0.99 T=0.01 Rc=100
    m m2 R=0.99 T=0.01 Rc=100
    link(l1, m1.p2, m1.p1, 80, m2.p1)
    cav cavity m1.p1.o
    pd REFL m1.p2.o
    pd CIRC m1.p1.o
    pd TRAN m2.p2.o
    modes(even, maxtem=10)
    """
)

model.beam_trace()

q_mismatch = finesse.BeamParam.overlap_contour(model.l1.p1.o.q, 0.1, 0)
model.l1.p1.o.q = q_mismatch

action = 'series(pseudo_lock_cavity(cavity), xaxis(m2.phi, lin, -2, 2, 100, True, name="xaxis"))'

labels = [f"phase {i}" for i in range(4)]
lss = ["-", "-", "--", "--"]
model.phase_config(zero_k00=False, zero_tem00_gouy=False)
out0 = model.run(action)
model.phase_config(zero_k00=True, zero_tem00_gouy=False)
out1 = model.run(action)
model.phase_config(zero_k00=False, zero_tem00_gouy=True)
out2 = model.run(action)
model.phase_config(zero_k00=True, zero_tem00_gouy=True)
out3 = model.run(action)


fig, axs = plt.subplots(4, 1, sharex=True, figsize=(6, 8))
for out, lbl, ls in zip([out0, out1, out2, out3], labels, lss):
    plt.sca(axs[0])
    plt.plot(out["xaxis"].x[0], out["xaxis"]["REFL"], label=lbl, ls=ls)
    plt.sca(axs[1])
    plt.plot(out["xaxis"].x[0], out["xaxis"]["CIRC"], ls=ls)
    plt.sca(axs[2])
    plt.plot(out["xaxis"].x[0], out["xaxis"]["TRAN"], ls=ls)
    plt.sca(axs[3])
    total = out["xaxis"]["REFL"] + out["xaxis"]["TRAN"]
    plt.plot(out["xaxis"].x[0], total, ls=ls)


plt.sca(axs[0])
plt.legend()
plt.title("Reflected")
plt.ylabel("Power [W]")
plt.sca(axs[1])
plt.title("Circulating")
plt.ylabel("Power [W]")
plt.sca(axs[2])
plt.title("Transmitted")
plt.ylabel("Power [W]")
plt.sca(axs[3])
plt.title("REFL + TRANS")
plt.ylabel("Power [W]")
plt.xlabel("End mirror tuning [deg]")
plt.tight_layout()
../../_images/phase_configurations_1_0.svg