Source code for tests.quad_damping.test_ligo_quad

"""
Unit tests and examples for damping the LIGO QUAD suspensions

Provided by Kevin Kuns
"""
import numpy as np
import pytest

from wield.control import SISO, MIMO
from wield.bunch import Bunch
from wield.pytest import fjoin, tjoin, dprint
from wield.control.plotting import plotTF
from wield.utilities.file_io import load, save


[docs] def test_convert_zpk_ss(): """ Converts a LIGO damping filter from ZPK to statespace and back to test numerical stability """ fname = fjoin('damping_filters.h5') zpk = load(fname).L dprint('testing!') filt_zpk = SISO.zpk(zpk.z, zpk.p, zpk.k) filt_ss = filt_zpk.asSS filt_zpk2 = filt_ss.asZPK # TODO - no reason to think these sets are sorted the same way for a direct comparison dprint(np.allclose(filt_zpk.z, filt_zpk2.z)) # TODO - no reason to think these sets are sorted the same way for a direct comparison dprint(np.allclose(filt_zpk.p, filt_zpk2.p)) # this should be True dprint(np.isclose(filt_zpk.k, filt_zpk2.k))
[docs] @pytest.mark.parametrize('quad_type', ['quad_full', 'quad_small']) def test_damp_quad(quad_type): """ Damp the undamped LIGO QUAD state space model Tests calculation of frequency responses and conversion of the resulting damped state space plant to ZPK """ # load quad state space ss_data = load(fjoin(quad_type + '.h5')) udamp_plant = MIMO.MIMOStateSpace( ss_data.A, ss_data.B, ss_data.C, ss_data.D, inputs=dict(ss_data.inputs), outputs=dict(ss_data.outputs), ) # load ZPK damping filters and convert to state space zpk_data = load(fjoin('damping_filters.h5')) damp_filts = Bunch() for dof, zpk in zpk_data.items(): damp_filts[dof] = SISO.zpk(zpk.z, zpk.p, zpk.k).asSS # Need to make the SISO damping filters into 1-1 MIMO filters with specified # inputs and outputs for making the feedback connections damp_plant = MIMO.ssjoinsum( udamp_plant, damp_filts.L.mimo('M0.L.o', 'M0.L.i'), damp_filts.T.mimo('M0.T.o', 'M0.T.i'), damp_filts.V.mimo('M0.V.o', 'M0.V.i'), damp_filts.P.mimo('M0.P.o', 'M0.P.i'), damp_filts.Y.mimo('M0.Y.o', 'M0.Y.i'), damp_filts.R.mimo('M0.R.o', 'M0.R.i'), ) # connect the displacements to the inputs to the damping filters # and then connect the outputs from the filters to the drives connections = [ ('M0.L.i', 'M0.disp.L'), ('M0.drive.L', 'M0.L.o'), ('M0.T.i', 'M0.disp.T'), ('M0.drive.T', 'M0.T.o'), ('M0.V.i', 'M0.disp.V'), ('M0.drive.V', 'M0.V.o'), ('M0.P.i', 'M0.disp.P'), ('M0.drive.P', 'M0.P.o'), ('M0.Y.i', 'M0.disp.Y'), ('M0.drive.Y', 'M0.Y.o'), ('M0.R.i', 'M0.disp.R'), ('M0.drive.R', 'M0.R.o'), ] # make the feedback and balance for numerical stability damp_plant = damp_plant.feedback_connect(connections=connections) udamp_plant = udamp_plant.balance() damp_plant = damp_plant.balance() # plot some transfer functions F_Hz = np.geomspace(0.05, 10, 1000) dprint('Calculating undamped L3') udamp_fresp_L3 = udamp_plant.siso('L3.disp.L', 'L3.drive.L').fresponse(f=F_Hz).tf dprint('Calculating damped L3') damp_fresp_L3 = damp_plant.siso('L3.disp.L', 'L3.drive.L').fresponse(f=F_Hz).tf dprint('Calculating undamped M0') udamp_fresp_M0 = udamp_plant.siso('M0.disp.L', 'M0.drive.L').fresponse(f=F_Hz).tf dprint('Calculating damped M0') damp_fresp_M0 = damp_plant.siso('M0.disp.L', 'M0.drive.L').fresponse(f=F_Hz).tf fig = plotTF(F_Hz, udamp_fresp_L3, label='Undamped') plotTF(F_Hz, damp_fresp_L3, *fig.axes, label='Damped', ls='--') fig.axes[0].legend() fig.axes[0].set_title('L3 to L3') fig.savefig(tjoin('L3.pdf')) fig = plotTF(F_Hz, udamp_fresp_M0, label='Undamped') plotTF(F_Hz, damp_fresp_M0, *fig.axes, label='Damped', ls='--') fig.axes[0].legend() fig.axes[0].set_title('M0 to M0') fig.savefig(tjoin('M0.pdf')) # make zpk filters and convert back to SS for (to, fr) in zip(['L3.disp.L', 'M0.disp.L'], ['L3.drive.L', 'M0.drive.L']): siso_udamp = damp_plant.siso(to, fr) siso_damp = udamp_plant.siso(to, fr) zpk_udamp = siso_udamp.asZPK zpk_damp = siso_damp.asZPK zpk_udamp.asSS zpk_damp.asSS