40m Quantum Limited Sensitivity - PRFPMI¶
In this example, we check that that we demonstrate how to put the 40m model in the PRFPMI state, but we don’t use any locking actions.
We start with our required imports:
import finesse
import finesse.analysis.actions as fac
from finesse.detectors import PowerDetector
import finesse.components as fc
from finesse_ligo.actions import DRFPMI_state
from finesse_40m.factory import FortyMeterFactory
import matplotlib.pyplot as plt
finesse.init_plotting()
import pprint
We then build the model and apply the PRFPMI state.
factory = FortyMeterFactory()
factory.reset()
factory.options.LSC.add_DOFs = False # Allow independantly controlling PRM position
# Print out build options
pprint.PrettyPrinter(indent=4, sort_dicts=True).pprint(
factory.options.toDict()
)
# Build model
model = factory.make()
model.modes(maxtem=4) # basic maxtem
model.run(DRFPMI_state('PRFPMI'))
assert model.SRM.misaligned == True
{ 'ASC': { 'add': False,
'add_AC_loops': True,
'add_DOFs': True,
'add_locks': True,
'add_output_detectors': True,
'add_readouts': True,
'close_AC_loops': False},
'BS_trans_arm': 'X',
'BS_type': 'thick',
'ETMAR': False,
'INPUT': {'add_IMC_and_IM1': False, 'set_IMC_mode': True},
'LSC': { 'add_AC_loops': False,
'add_DOFs': False,
'add_locks': False,
'add_output_detectors': False,
'add_readouts': True,
'close_AC_loops': False},
'OUTPUT': {'readout': None},
'PR2_PR3_substrates': True,
'QUAD_suspension_kwargs': {},
'QUAD_suspension_model': None,
'add_118MHz': False,
'add_11MHz': True,
'add_165MHz': False,
'add_33MHz': True,
'add_45MHz': False,
'add_55MHz': True,
'add_9MHz': False,
'add_detectors': True,
'add_transmon': False,
'fake_prc_gouy': False,
'fake_src_gouy': False,
'materials': { 'test_mass_substrate': <finesse.materials.Material object at 0x7f9ab8ac9590>},
'test_mass_wedge': False}
We then manually define the operating point and check that the model has reached it. This is checking:
The nodes are connected correctly.
The mode matching is good (see maxtem=4 above).
The IFO is at the correct operating point.
# Bring cavities onto resonance
dc_offset = 125e-6 # degrees
model.ITMY.phi=0 - dc_offset
model.ETMY.phi=0 - dc_offset
model.PRM.phi = 0
# Get pds
PDs = [
detector for detector in model.detectors if isinstance(detector, PowerDetector)
]
sim = model.run(fac.Noxaxis())
for detector in PDs:
print(f"{detector} = {sim[detector]:.1e} W")
assert 3700 < sim['Px'] < 3800
assert 3700 < sim['Py'] < 3800
assert 14 < sim['Pinx'] < 15
assert 14 < sim['Piny'] < 15
assert 29 < sim['Pprc'] < 30
assert sim['Psrc'] < 1
PowerDetector('Px') = 3.8e+03 W
PowerDetector('Pinx') = 1.5e+01 W
PowerDetector('Py') = 3.8e+03 W
PowerDetector('Piny') = 1.5e+01 W
PowerDetector('Pprc') = 2.9e+01 W
PowerDetector('Psrc') = 0.0e+00 W
PowerDetector('Pin') = 8.0e-01 W
PowerDetector('PreflPRM') = 2.0e-01 W
PowerDetector('Prefl') = 2.0e-01 W
PowerDetector('Ppop') = 0.0e+00 W
For completeness, we print out the tunings so you can compare your model against this one.
def print_tunings(modelin, ARS=False):
comps = list(modelin.components)
comps.sort(key=lambda comp: comp.name)
if not ARS:
comps = [comp for comp in comps if comp.name[-2:] != "AR"]
for comp in comps:
if isinstance(comp, (fc.Mirror, fc.Beamsplitter)):
print(comp.name, comp.phi)
print_tunings(model)
AS1 0.0 degrees
AS2 0.0 degrees
AS3 0.0 degrees
AS4 0.0 degrees
AS_Window_Air 0.0 degrees
AS_Window_Vac 0.0 degrees
BHDBS 0.0 degrees
BHDBS_LO 0.0 degrees
BHDBS_OUT2 0.0 degrees
BS 0.0 degrees
BSARAS BS.phi degrees
BSARX BS.phi degrees
ETMX 0.0 degrees
ETMY -0.000125 degrees
ITMX 0.0 degrees
ITMY -0.000125 degrees
LO1 0.0 degrees
LO2 0.0 degrees
LO3 0.0 degrees
LO4 0.0 degrees
POP_SM4 0.0 degrees
POP_SM5 0.0 degrees
POP_Window_Air 0.0 degrees
POP_Window_Vac 0.0 degrees
PR2 0.0 degrees
PR2AR_for PR2.phi degrees
PR2AR_rev PR2.phi degrees
PR3 0.0 degrees
PRM 0.0 degrees
SR2 0.0 degrees
SRM 0.0 degrees
We can now plot some cavity scans for reference.
ax1 = fac.Xaxis(model.L0.f, 'lin', -1.1 * model.cavXARM.FSR / 2, 1.1 * model.cavXARM.FSR / 2, 1000)
ax2 = fac.Xaxis(model.PRM.phi, 'lin', -95, 95, 1000)
The full arm FSR:
out = model.run(ax1, progress_bar=True)
out.plot(*PDs, logy=True)
{finesse.detectors.powerdetector.PowerDetector: <Figure size 576x355.968 with 1 Axes>,
'Px': <Figure size 576x355.968 with 1 Axes>,
'Pinx': <Figure size 576x355.968 with 1 Axes>,
'Py': <Figure size 576x355.968 with 1 Axes>,
'Piny': <Figure size 576x355.968 with 1 Axes>,
'Pprc': <Figure size 576x355.968 with 1 Axes>,
'Psrc': <Figure size 576x355.968 with 1 Axes>,
'Pin': <Figure size 576x355.968 with 1 Axes>,
'PreflPRM': <Figure size 576x355.968 with 1 Axes>,
'Prefl': <Figure size 576x355.968 with 1 Axes>,
'Ppop': <Figure size 576x355.968 with 1 Axes>}
The PRC FSR:
out = model.run(ax2, progress_bar=True)
out.plot(*PDs, logy=True)
{finesse.detectors.powerdetector.PowerDetector: <Figure size 576x355.968 with 1 Axes>,
'Px': <Figure size 576x355.968 with 1 Axes>,
'Pinx': <Figure size 576x355.968 with 1 Axes>,
'Py': <Figure size 576x355.968 with 1 Axes>,
'Piny': <Figure size 576x355.968 with 1 Axes>,
'Pprc': <Figure size 576x355.968 with 1 Axes>,
'Psrc': <Figure size 576x355.968 with 1 Axes>,
'Pin': <Figure size 576x355.968 with 1 Axes>,
'PreflPRM': <Figure size 576x355.968 with 1 Axes>,
'Prefl': <Figure size 576x355.968 with 1 Axes>,
'Ppop': <Figure size 576x355.968 with 1 Axes>}
For completeness, the quantum-noise limited response of the 40m.
model2 = model.deepcopy()
model2.parse("""
# Differentially modulate the arm lengths
pendulum susEX ETMX.mech mass=1 fz=0.8 Qz=100
pendulum susEY ETMY.mech mass=1 fz=1.0 Qz=100
pendulum susIX ITMX.mech mass=1 fz=1.2 Qz=100
pendulum susIY ITMY.mech mass=1 fz=1.4 Qz=100
# Differentially modulate the arm lengths
fsig(1)
sgen darmx LX.h
sgen darmy LY.h phase=180
# Output the full quantum noise limited sensitivity
qnoised NSR_with_RP SRM.p2.o nsr=True
# Output just the shot noise limited sensitivity
qshot NSR_without_RP SRM.p2.o nsr=True
# We could also display the quantum noise and the signal
# separately by uncommenting these two lines.
# qnoised noise srm.p2.o
# pd1 signal srm.p2.o f=fsig
""")
ax = fac.Xaxis(model2.darmx.f, 'log', 0.3, 100e3, 300, name='LF')
out = model2.run(ax,progress_bar=True)
fig, ax1 = plt.subplots(ncols=1,sharey=True,figsize=(7,3))
ax1.loglog(out.x0,2*out['NSR_with_RP'], c='r', ls='--')
ax1.set_ylabel('Sensitivity [1/sqrt(Hz)]')
Text(0, 0.5, 'Sensitivity [1/sqrt(Hz)]')
Recall the factor 2 from 40m Quantum Limited Sensitivity - Simple Michelson.
assert 1e-20 < 2*out['NSR_with_RP'][150] < 8e-20