T_ADY_make_sys

test.ASC_SOLVER.T_ADY_make_sys

This File has the sole purpose of creating the ASC DHARD Y Model that is then exported to the buzz repository.

pytest-html report

Functions

FBNSSS_DARM([return_name, return_scale])

FBNSSS_Fit([gain, return_name, return_scale])

FBNSSS_Hand([return_name, return_scale])

FBNSsimpSS([return_name, lo_ord, return_scale])

This is a pytest needing documentation

FFlatSS([gain, return_name])

This is a pytest needing documentation

addSS([namespace, dt, sub, outSufx])

Create a state space model for an adder.

bode(sys[, axB, F_Hz, omega_limits, ...])

sys should be a wield.control.SISO object

delayDrive([namespace, Sp, delay, order, ...])

This is a pytest needing documentation

delaySS([namespace, delay, order, numins, dt])

Create a state space model for the delay block.

multi_bode(axB[, F_Hz, include_zp])

Plot multiple bode plots at once.

nullSS([namespace, gain])

Create a state space model for the null block.

test_Make_ADY(folder)

This is the main function that is called to create the model for the ASC DHARD Y.

transposeSys(sys, FOM_ns)

This is a pytest needing documentation

ws_tf2ss(z, p, k[, gain, mfactor, angular])

Takes a python control zpk and returns a python control statespace.

Details

FBNSSS_DARM(return_name=False, return_scale=False)[source]
code
docstring
"""

"""
 1def FBNSSS_DARM(return_name=False, return_scale = False):
 2
 3    if return_name:
 4        name = "FOM BNS (Hand Fit)"
 5        return name
 6
 7    #BNS_zpk = file_io.load(fjoin('ExampleModels_DARMFOM/BNS_FOM_from_DARM.yml'))
 8    BNS_zpk = file_io.load(fjoin('ExampleModels_DARMFOM/BNS_FOM_IR.yml'))
 9    F_z = np.array(BNS_zpk["z"], dtype=np.complex128)
10    F_p = np.array(BNS_zpk["p"], dtype=np.complex128)
11    F_k = BNS_zpk["k"]
12
13    F = SISO.zpk(F_z, F_p, F_k).asSS.mimo("FBNS.out", "FBNS.in")
14    F, scale = ssutil.normalize_gain(F, norm=1, return_scale=True)
15    if return_scale:
16        return scale
17    else:
18        return F
pytest information

This code is wrapped in a pytest function using conventions detailed in pytest_conventions. The full name of this test, as known by the documentation, is:

test.ASC_SOLVER.T_ADY_make_sys.FBNSSS_DARM

The full name is useful when building documentation, to link a reference to this page using :func:`name`, or directly include it with an autofunction directive. The collapse nodes below show every instance of the test run. There may only be one, but if the test was run multiple times through pytest parametrizations, the list can be longer.

FBNSSS_Fit(gain=1, return_name=False, return_scale=False)[source]
code
docstring
"""

"""
 1def FBNSSS_Fit(gain=1, return_name=False, return_scale = False):
 2
 3    if return_name:
 4        name = "FOM BNS"
 5        return name
 6
 7    if gain != 1:
 8        NotImplementedError("This function does not support gain scaling")
 9
10    BNS_zpk = file_io.load(fjoin('ExampleModels_newFOM/BNS_FOM.yml'))
11    print(BNS_zpk['z'])
12    F_z = np.array(BNS_zpk["z"], dtype=np.complex128)
13    #BNS_zpk["p"].append(BNS_zpk["p"][-1])
14    F_p = np.array(BNS_zpk["p"], dtype=np.complex128)
15    F_k = BNS_zpk["k"]
16
17    #print(len(F_z))
18    #print(len(F_p))
19    F_mod = SISO.zpk(F_z, F_p, F_k).asSS
20    F_iod = {"FBNS.in": 0, "FBNS.out": 0}
21    F = ssutil.wieldSS(F_mod.A, F_mod.B, F_mod.C, F_mod.D, iod=F_iod)
22    F, scale = ssutil.normalize_gain(F, norm=1, return_scale=True)
23    if return_scale:
24        return scale
25    else:
26        return F
pytest information

This code is wrapped in a pytest function using conventions detailed in pytest_conventions. The full name of this test, as known by the documentation, is:

test.ASC_SOLVER.T_ADY_make_sys.FBNSSS_Fit

The full name is useful when building documentation, to link a reference to this page using :func:`name`, or directly include it with an autofunction directive. The collapse nodes below show every instance of the test run. There may only be one, but if the test was run multiple times through pytest parametrizations, the list can be longer.

FBNSSS_Hand(return_name=False, return_scale=False)[source]
code
docstring
"""

"""
 1def FBNSSS_Hand(return_name=False, return_scale = False):
 2
 3    if return_name:
 4        name = "FOM BNS (Hand Fit)"
 5        return name
 6
 7    BNS_zpk = file_io.load(fjoin('ExampleModels_newFOM/BNS_FOM_handfit.yml'))
 8    F_z = np.array(BNS_zpk["z"], dtype=np.complex128)
 9    F_p = np.array(BNS_zpk["p"], dtype=np.complex128)
10    F_k = BNS_zpk["k"]
11
12    F = SISO.zpk(F_z, F_p, F_k).asSS.mimo("FBNS.out", "FBNS.in")
13    F, scale = ssutil.normalize_gain(F, norm=1, return_scale=True)
14    if return_scale:
15        return scale
16    else:
17        return F
pytest information

This code is wrapped in a pytest function using conventions detailed in pytest_conventions. The full name of this test, as known by the documentation, is:

test.ASC_SOLVER.T_ADY_make_sys.FBNSSS_Hand

The full name is useful when building documentation, to link a reference to this page using :func:`name`, or directly include it with an autofunction directive. The collapse nodes below show every instance of the test run. There may only be one, but if the test was run multiple times through pytest parametrizations, the list can be longer.

FBNSsimpSS(return_name=False, lo_ord=4, return_scale=False)[source]

This is a pytest needing documentation

code
 1def FBNSsimpSS(return_name=False, lo_ord=4, return_scale=False):
 2    if return_name:
 3        name = "FOM BNS Simple"
 4        return name
 5
 6    BNS_zpk = file_io.load(fjoin('FOMs/FBNSsimp_FOM.yml'))
 7    print(BNS_zpk['z'])
 8    F_z = np.array(BNS_zpk["z"], dtype=np.complex128)
 9    F_p = np.array(BNS_zpk["p"], dtype=np.complex128)
10    F_k = BNS_zpk["k"]
11
12    F = SISO.zpk(F_z, F_p, F_k).asSS.mimo("FBNS.out", "FBNS.in")
13    F, scale = ssutil.normalize_gain(F, norm=1, return_scale=True)
14    if return_scale:
15        return scale
16    else:
17        return F
pytest information

This code is wrapped in a pytest function using conventions detailed in pytest_conventions. The full name of this test, as known by the documentation, is:

test.ASC_SOLVER.T_ADY_make_sys.FBNSsimpSS

The full name is useful when building documentation, to link a reference to this page using :func:`name`, or directly include it with an autofunction directive. The collapse nodes below show every instance of the test run. There may only be one, but if the test was run multiple times through pytest parametrizations, the list can be longer.

FFlatSS(gain=1, return_name=False)[source]

This is a pytest needing documentation

code
1def FFlatSS(gain=1, return_name=False):
2    if return_name:
3        name = "FOM Flat"
4        return name
5
6    return SISO.zpk([], [], gain).asSS.mimo("F2.out", "F2.in")
pytest information

This code is wrapped in a pytest function using conventions detailed in pytest_conventions. The full name of this test, as known by the documentation, is:

test.ASC_SOLVER.T_ADY_make_sys.FFlatSS

The full name is useful when building documentation, to link a reference to this page using :func:`name`, or directly include it with an autofunction directive. The collapse nodes below show every instance of the test run. There may only be one, but if the test was run multiple times through pytest parametrizations, the list can be longer.

addSS(namespace='T', dt=0.0001, sub=False, outSufx=None)[source]

Create a state space model for an adder. It has two inputs and one output.

Parameters:
  • namespace (string) – The namespace to use for the model i.e. the letter that comes at the beginning of the input and output names. Defaults to ‘T’.

  • dt (float, optional) – The time step. Defaults to 1e-4.

  • sub (bool, optional) – If true, the model will be a subtractor. Defaults to False.

Returns:

Returns the local name space for the function including the state space model as mod, input output dictionary as iod, and namespace.

Return type:

wield.bunch

code
docstring
"""Create a state space model for an adder. It has two inputs and one output.

Args:
    namespace (string): The namespace to use for the model i.e. the letter that comes at the beginning of the input and output names. Defaults to 'T'.
    dt (float, optional): The time step. Defaults to 1e-4.
    sub (bool, optional): If true, the model will be a subtractor. Defaults to False.

Returns:
    wield.bunch: Returns the local name space for the function including the state space model as `mod`, input output dictionary as `iod`, and namespace.
"""
 1def addSS(namespace='T', dt=1e-4, sub=False, outSufx = None):
 2
 3    A = np.zeros([0,0]) # Construct the A state matrix
 4    B = np.zeros([2,0]) # Construct the B state matrix
 5    C = np.zeros([0,1]) # Construct the C state matrix
 6    if sub:
 7        D = np.array([[1, -1]]) # Construct the D state matrix for a subtractor
 8    else:
 9        D = np.array([[1, 1]]) # Construct the D state matrix
10    if outSufx == None:
11        iod = {namespace+'.in.1': 0, namespace+'.in.2': 1, namespace+'.out': 0} # Input output dictionary
12    else:
13        iod = {namespace+'.in.1': 0, namespace+'.in.2': 1, namespace+'.out.'+outSufx: 0} # Input output dictionary
14    return ssutil.wieldSS(A, B, C, D, iod=iod)
pytest information

This code is wrapped in a pytest function using conventions detailed in pytest_conventions. The full name of this test, as known by the documentation, is:

test.ASC_SOLVER.T_ADY_make_sys.addSS

The full name is useful when building documentation, to link a reference to this page using :func:`name`, or directly include it with an autofunction directive. The collapse nodes below show every instance of the test run. There may only be one, but if the test was run multiple times through pytest parametrizations, the list can be longer.

bode(sys, axB=None, F_Hz=None, omega_limits=None, include_zp=True, label=None, **kwargs)[source]

sys should be a wield.control.SISO object

code
docstring
"""
sys should be a wield.control.SISO object
"""
 1def bode(
 2    sys,
 3    axB=None,
 4    F_Hz=None,
 5    omega_limits=None,
 6    include_zp = True,
 7    label=None,
 8    **kwargs
 9):
10
11    if axB is None:
12        axB = mplfigB(Nrows = 2)
13
14    if include_zp:
15        z, p = sys._zp
16        z = z[z.imag > 0]
17        p = p[p.imag > 0]
18        F_include = np.sort(np.concatenate(
19            [
20                z.imag,
21                p.imag,
22                z.imag - abs(z.real) - 1e-6,
23                z.imag + abs(z.real) + 1e-6,
24                p.imag - abs(p.real) - 1e-6,
25                p.imag + abs(p.real) + 1e-6,
26            ]
27        )) / (2 * np.pi)
28        F_include = F_include[F_include > 0]
29
30        if omega_limits is None:
31            omega_limits = (
32                (F_include[0] + 1e-6) / 3,
33                F_include[-1] * 3
34            )
35
36    if F_Hz is None:
37        F_Hz = np.geomspace(omega_limits[0], omega_limits[1], 1000)
38
39    if include_zp:
40        print("F_include", F_include)
41        F_Hz = np.sort(np.concatenate([F_Hz, F_include]))
42
43    fr = sys.fresponse(f=F_Hz)
44    axB.ax0.loglog(*fr.fplot_mag, label=label, **kwargs)
45    if hasattr(axB, 'ax1'):
46        axB.ax1.semilogx(*fr.fplot_deg225, label=label, **kwargs)
47    return axB
pytest information

This code is wrapped in a pytest function using conventions detailed in pytest_conventions. The full name of this test, as known by the documentation, is:

test.ASC_SOLVER.T_ADY_make_sys.bode

The full name is useful when building documentation, to link a reference to this page using :func:`name`, or directly include it with an autofunction directive. The collapse nodes below show every instance of the test run. There may only be one, but if the test was run multiple times through pytest parametrizations, the list can be longer.

delayDrive(namespace='D', Sp=None, delay=0.001, order=1, numins=1, dt=0.0001)[source]

This is a pytest needing documentation

code
 1def delayDrive(namespace='D', Sp=None, delay=1e-3, order=1, numins=1, dt=1e-4):
 2    D = delaySS(namespace=namespace, delay=delay, order=order, numins=numins, dt=dt)
 3
 4    if Sp is None or Sp == 1:
 5        #assert(False)
 6        return D
 7
 8    #rename the input for pending merge
 9    D.iod[namespace + '.in.2'] = D.iod[namespace + '.in']
10    del D.iod[namespace + '.in']
11
12    #check that it only has 1 input and one output (THIS IS A HACKY WAY TO TEST)
13    assert(len(Sp.iod) == 2)
14
15    print(Sp.iod)
16    Sp.iod.clear()
17    Sp.iod[namespace + '.in'] = 0
18    Sp.iod[namespace + '.out.1'] = 0
19    print(Sp.iod)
20
21    Dx = ssutil.multiconnect([Sp, D], [[namespace+'.in.2', namespace+'.out.1']])
22    print(Dx.iod)
23    return Dx
pytest information

This code is wrapped in a pytest function using conventions detailed in pytest_conventions. The full name of this test, as known by the documentation, is:

test.ASC_SOLVER.T_ADY_make_sys.delayDrive

The full name is useful when building documentation, to link a reference to this page using :func:`name`, or directly include it with an autofunction directive. The collapse nodes below show every instance of the test run. There may only be one, but if the test was run multiple times through pytest parametrizations, the list can be longer.

delaySS(namespace='D', delay=0.001, order=1, numins=1, dt=0.0001)[source]

Create a state space model for the delay block. It has one input and one output.

Parameters:
  • namespace (str, optional) – The namespace for the delay block. Defaults to ‘D’.

  • delay (_type_, optional) – The delay in seconds. Defaults to 1e-3.

  • order (int, optional) – Order of the filter. Defaults to 1.

  • numins (int, optional) – Number of inputs. Defaults to 1.

  • dt (_type_, optional) – The discretization time step. Defaults to 1e-4.

Returns:

Returns the local name space for the function including the state space model as mod, input output dictionary as iod, and namespace.

Return type:

wield.bunch

code
docstring
"""Create a state space model for the delay block. It has one input and one output.

Args:
    namespace (str, optional): The namespace for the delay block. Defaults to 'D'.
    delay (_type_, optional): The delay in seconds. Defaults to 1e-3.
    order (int, optional): Order of the filter. Defaults to 1.
    numins (int, optional): Number of inputs. Defaults to 1.
    dt (_type_, optional): The discretization time step. Defaults to 1e-4.

Returns:
    wield.bunch: Returns the local name space for the function including the state space model as `mod`, input output dictionary as `iod`, and namespace.
"""
 1def delaySS(namespace='D', delay=1e-3, order=1, numins=1, dt=1e-4):
 2
 3    if delay==0:
 4        print('Delay is zero, using nullSS')
 5        D_mod = nullSS().mod
 6    else:
 7        # take the poles of this normalized bessel filter (delay=1s)
 8        z, p, k = scipy.signal.besselap(order, norm="delay")
 9
10        # now rescale for desired delay
11        roots = p / delay * 2
12        if order % 2 == 0:
13            k = 1
14        else:
15            k = -1
16
17        #siso_rep = SISO.zpk(-roots.conjugate(), roots, k)
18        D_res = control.zpk(-roots.conjugate(), roots, k)
19        D_mod = control.tf2ss(D_res)
20
21    B_blocked = D_mod.B
22    D_blocked = D_mod.D
23    for ii in range(numins-1):
24        B_blocked = np.block([[B_blocked, D_mod.B]])
25        D_blocked = np.block([[D_blocked, D_mod.D]])
26
27    mod = control.ss(D_mod.A, B_blocked, D_mod.C, D_blocked) # Create the system
28    mod_dis = control.c2d(mod, dt) # Discretize the system
29    iod = dict({namespace+'.in': 0, namespace+'.out': 0}) # Input output dictionary
30    for ii in range(numins-1):
31        iod[namespace+'.in.'+str(ii+1)] = ii+1
32
33    return Bunch(locals())
pytest information

This code is wrapped in a pytest function using conventions detailed in pytest_conventions. The full name of this test, as known by the documentation, is:

test.ASC_SOLVER.T_ADY_make_sys.delaySS

The full name is useful when building documentation, to link a reference to this page using :func:`name`, or directly include it with an autofunction directive. The collapse nodes below show every instance of the test run. There may only be one, but if the test was run multiple times through pytest parametrizations, the list can be longer.

multi_bode(axB, F_Hz=None, include_zp=True, **kwargs)[source]

Plot multiple bode plots at once.

The main advantage is that the scale of the axes can be better auto-determined to capture all known poles and zeros. The input arguments should all be dictionaries containing the bode kwargs.

the usage should be

the kwargs on the top call are passed into all sub calls

with multi_bode(axB=axB, **kw_cmn) as bode:

bode(sisoA, label=’A’, **kw) bode(sisoB, label=’B’, **kw) bode(sisoC, label=’C’, **kw)

axB.save(‘figname.pdf’)

nullSS(namespace='N', gain=1)[source]

Create a state space model for the null block. It has one input and one output.

Parameters:
  • namespace (str, optional) – The namespace to use for the model i.e. the letter that comes at the beginning of the input and output names. Defaults to ‘N’.

  • gain (float, optional) – The gain of the null block. Defaults to 1.

Returns:

Returns Wield MIMO statespace

Return type:

MIMO Statespace

code
docstring
"""Create a state space model for the null block. It has one input and one output.

Args:
    namespace (str, optional): The namespace to use for the model i.e. the letter that comes at the beginning of the input and output names. Defaults to 'N'.
    gain (float, optional): The gain of the null block. Defaults to 1.

Returns:
    MIMO Statespace: Returns Wield MIMO statespace
"""
1def nullSS(namespace='N', gain=1):
2
3
4    A = np.zeros([0,0]) # Construct the A state matrix
5    B = np.zeros([1,0]) # Construct the B state matrix
6    C = np.zeros([0,1]) # Construct the C state matrix
7    D = np.array([[gain]]) # Construct the D state matrix 
8    iod = dict({namespace+'.in': 0, namespace+'.out': 0}) # Input output dictionary
9    return ssutil.wieldSS(A, B, C, D, iod=iod)
pytest information

This code is wrapped in a pytest function using conventions detailed in pytest_conventions. The full name of this test, as known by the documentation, is:

test.ASC_SOLVER.T_ADY_make_sys.nullSS

The full name is useful when building documentation, to link a reference to this page using :func:`name`, or directly include it with an autofunction directive. The collapse nodes below show every instance of the test run. There may only be one, but if the test was run multiple times through pytest parametrizations, the list can be longer.

test_Make_ADY(folder)[source]

This is the main function that is called to create the model for the ASC DHARD Y.

code
docstring
"""
This is the main function that is called to create the model for the ASC DHARD Y.
"""
  1@pytest.mark.parametrize(
  2    'folder', [
  3        #'ExampleModels_rescale',
  4        'ExampleModels',
  5        'ExampleModels_working',
  6        'ExampleModels_working_F3',
  7        'ExampleModels_newFOM',
  8        'ExampleModels_newFOM_F3',
  9        'ExampleModels_DARMFOM'
 10    ]
 11)
 12@pytest.mark.gitlabCI
 13@pytest.mark.ADY
 14def test_Make_ADY(folder):
 15
 16    S = ssutil.loadSys(fjoin(folder, 'ADY_E_from_fit.mat'))
 17    O = ssutil.loadSys(fjoin(folder, 'ADY_M_from_fit.mat'))
 18    P_fname = 'ADY_plant_from_fit.mat'
 19    P = ssutil.loadSys(fjoin(folder, P_fname))
 20
 21    # w2_rescale = 2e5
 22    w2_rescale = 1e6
 23    S = (w2_rescale * S.siso('S.out', 'S.in')).mimo('S.out', 'S.in')
 24    O = (w2_rescale * O.siso('O.out', 'O.in')).mimo('O.out', 'O.in')
 25
 26    if '_newFOM' in folder or '_newFOM_F3' in folder:
 27        FBNS_func = FBNSSS_Hand
 28        FBNS = FBNS_func()
 29        FBNS_scale = FBNS_func(return_scale=True)
 30    elif 'DARMFOM' in folder:
 31       FBNS_func = FBNSSS_DARM
 32       FBNS = FBNS_func()
 33       FBNS_scale = FBNS_func(return_scale=True)
 34    else:
 35        FBNS_func = FBNSsimpSS
 36        FBNS = FBNS_func()
 37        FBNS_scale = FBNS_func(return_scale=True)
 38
 39        omega_limits=[1e-2, 1e4]
 40        axB = ssutil.bode(FBNS.siso('FBNS.out', 'FBNS.in'), omega_limits=omega_limits, label='Simple FBNS')
 41        axB = ssutil.bode(FBNSSS_Hand().siso('FBNS.out', 'FBNS.in'), omega_limits=omega_limits, axB=axB, label='Hand Fit FBNS')
 42        axB = ssutil.bode(FBNSSS_Fit().siso('FBNS.out', 'FBNS.in'), omega_limits=omega_limits, axB=axB, label='FBNS From Data')
 43        axB.save(tjoin('BNS_FOMS_Comp.pdf'))
 44        axB.save(tjoin('BNS_FOMS_Comp.png'))
 45
 46    FFlat = FFlatSS()
 47
 48    # Inject the coupling into the BNS FOM, normalize it to Hinf=1 and then collect its scale
 49    Coup = ssutil.loadSys(fjoin(folder, 'A2L_coupling_with_cal.mat')) # This is the Angle to length coupling it would be multiplied by the BNS FOM
 50    FBNS = ssutil.multiconnect([Coup, FBNS], [['FBNS.in', 'COUP.out']])
 51    FBNS = ssutil.truncate_io(FBNS, ['COUP.in'], ['FBNS.out','COUP.out']) #commented out to display DARM Spectrum
 52    #FBNS = ssutil.rename_io(FBNS, 'FBNS.in', 'FBNS.nocoup.in') # so that you can see the FBNS with no coupling
 53    FBNS = ssutil.rename_io(FBNS, 'COUP.out', 'FBNS.DARM.out') # to see DARM Spectrum
 54    FBNS = ssutil.rename_io(FBNS, 'COUP.in', 'FBNS.in')
 55    print(FBNS.iod)
 56
 57    FBNS_Trash, Coup_scale = ssutil.normalize_gain(ssutil.truncate_io(FBNS, ['FBNS.in'], ['FBNS.out']), norm=1, return_scale=True, method='fq_resp')
 58    del FBNS_Trash
 59    FBNS = ssutil.scale_io(FBNS, 'FBNS.out', Coup_scale) # using this to scale preserves the DARM.out output
 60
 61    FBNS_scale = FBNS_scale * Coup_scale
 62    np.savetxt(fjoin(folder, 'FBNS_scale.txt'), [FBNS_scale])
 63    print('FBNS scale', FBNS_scale)
 64
 65    current_range = np.loadtxt(fjoin(folder, 'FBNS_Current_range.txt')) # Saved by the normalization in the make function
 66    io_scales = Bunch(
 67        FBNS = FBNS_scale,  # will need to apply this to the BNS FOM
 68        w2_rescale = w2_rescale,  # will need to divide by this on both FOMs
 69        # will need to be applied only to the Flat fom since the A2L_coupling_with_cal includes it as a factor
 70        ct2rad = 5.2e-11,  # Calibration from https://alog.ligo-wa.caltech.edu/aLOG/index.php?callRep=69551
 71        strain2m = 1/3995,  # Representing the 4km arm length. Strain is h = dL/L where L = 3995 m. The coupling is "I" is in rad to displacement so we need to convert it to strain for the BNS FOM which is in strain
 72        current_range = current_range,
 73    )
 74    io_scales.RMS_cal_F1 = 1/io_scales.FBNS * io_scales.strain2m / io_scales.w2_rescale
 75    io_scales.RMS_cal_F2 = io_scales.ct2rad / io_scales.w2_rescale
 76    file_io.save(fjoin(folder, 'io_scales.yml'), dict(io_scales))
 77
 78    omega_limits=[1e-2, 1e4]
 79
 80    omega_limits_noise = [1e-1, 1e3]
 81    axN = ssutil.bode(ssutil.asSISO(S), omega_limits=omega_limits_noise, label='Seismic')
 82    axN = ssutil.bode(ssutil.asSISO(O), axB=axN, omega_limits=omega_limits_noise, label='Meas. Noise')
 83    axN = ssutil.bode(ssutil.asSISO(P), axB=axN, omega_limits=omega_limits_noise, label='Plant')
 84    axN = ssutil.bode(ssutil.asSISO(S.siso('S.out', 'S.in') * P.siso('P.out', 'P.in')), axB=axN, omega_limits=omega_limits_noise, label='S*P')
 85    axN.save(tjoin('Noise_bode.png'))
 86    axN.save(tjoin('Noise_bode.pdf'))
 87
 88
 89    # control.bode(S.mod, dB=False, Hz=True, omega_limits=omega_limits, label='Seismic')
 90    # control.bode(O.mod, dB=False, Hz=True, omega_limits=omega_limits, label='Meas. Noise')
 91    # control.bode(P.mod, dB=False, Hz=True, omega_limits=omega_limits, label='Plant')
 92    # control.bode((S.siso('S.out', 'S.in') * P.siso('P.out', 'P.in')).mimo('out', 'in').mod, dB=False, Hz=True, omega_limits=omega_limits, label='S*P')
 93    # plt.legend()
 94    # plt.savefig(tjoin('Noise_bode.pdf'), bbox_inches='tight')
 95    # plt.savefig(tjoin('Noise_bode.png'), bbox_inches='tight', dpi=300)
 96    # plt.close()
 97
 98    omega_limits_fom = np.array([1e-1, 1e5])*2*np.pi
 99    axFOM = ssutil.bode(FBNS.siso('FBNS.out', 'FBNS.in'), omega_limits=omega_limits_fom, label='FBNS')
100    axFOM = ssutil.bode(FFlat.siso(iodutil.listoutputs(FFlat)[0], iodutil.listinputs(FFlat)[0]), axB=axFOM, omega_limits=omega_limits_fom, label='FFlat')
101    axFOM.save(tjoin('FOM_bode.pdf'))
102    axFOM.save(tjoin('FOM_bode.png'))
103    # control.bode(FBNS.mod, dB=True, Hz=True, omega_limits=omega_limits, label='FBNS')
104    # control.bode(FFlat.mod, dB=True, Hz=True, omega_limits=omega_limits, label='FFlat')
105    # plt.legend()
106    # plt.savefig(tjoin('FOM_bode.pdf'))
107    # plt.savefig(tjoin('FOM_bode.png'))
108    # plt.close()
109
110    #make the SO
111    #conlist =[['T_SO.in.1', 'O.out'], ['T_SO.in.2','S.out']]
112    #T_SO = addSS(namespace='T_SO', sub=True)
113    #SO = ssutil.multiconnect([S, O, T_SO], conlist)
114    #SO = ssutil.truncate_io(SO, ['O.in', 'S.in'], ['T_SO.out', 'S.out'])
115    #SO = ssutil.rename_io(SO, 'T_SO.out', 'O.out')
116
117    #control.bode(SO.mod[SO.iod['S.out'], SO.iod['S.in']], dB=True, Hz=True, omega_limits=omega_limits, label='S to S')
118    #control.bode(SO.mod[SO.iod['O.out'], SO.iod['O.in']], dB=True, Hz=True, omega_limits=omega_limits, label='O to O')
119    #control.bode(SO.mod[SO.iod['O.out'], SO.iod['S.in']], dB=True, Hz=True, omega_limits=omega_limits, label='S to O', linestyle='--', linewidth=5)
120    #control.bode(S.mod, dB=True, Hz=True, omega_limits=[1e-2, 1e3], label='Orig. S', linestyle='dotted', linewidth=4)
121    #control.bode(O.mod, dB=True, Hz=True, omega_limits=[1e-2, 1e3], label='Orig. O', linestyle='dotted', linewidth=4)
122    #plt.legend(fontsize=8)
123    #plt.savefig(tjoin('SO_bode.pdf'))
124    #plt.close()
125    if '_F3' in folder:
126        extras = 'F3_withP'
127    else:
128        extras = None
129
130    SPOFF = ssutil.makeSPOFF(S, P, O, FBNS, FFlat, diagnostic=True, extras=extras, balance=True)
131    #print('SPOFF', SPOFF.iod)
132    #SPOFF = ssutil.balance_sys_gain(SPOFF)
133    omega_limits=[1e-2, 1e3]
134
135    axB = mplfigB(Nrows=2)
136    F_Hz = np.geomspace(1e-2, 20, 1000)
137    with multi_bode(axB=axB, F_Hz = F_Hz) as bode:
138        bode(P['P.out', 'P.in'], label='P alone', linewidth=2, color='dodgerblue')
139        bode(SPOFF['P.out', 'P.in'], label='P to P in SPOFF', color='orange')
140        bode(SPOFF['P.out', 'S.in'], label='S to P', color='green')
141        bode(SPOFF['S.out', 'S.in'], label='S to S', linestyle='dotted', linewidth=4, color='green')
142        bode(SPOFF['P.out', 'SA.in'], linestyle='--', label='P Recombined', linewidth=4, color='dodgerblue')
143        bode(SPOFF['S.out', 'SA.in'], label='P that moved to S', color='dodgerblue', linestyle='dotted', linewidth=6)
144        bode(SPOFF['G.out', 'S.in'], label='Orig. S (from SPOFF)', color='red')
145        bode(S['S.out', 'S.in'], label='Orig. S alone', linestyle='dotted', linewidth=4, color='red')
146    axB.ax1.legend(fontsize=5)
147    axB.save(tjoin('SPOFF_diagnostic_bode.pdf'))
148    axB.save(tjoin('SPOFF_diagnostic_bode.png'))
149
150    axB = mplfigB(Nrows=2)
151    F_Hz = np.geomspace(1e-2, 20, 1000)
152    with multi_bode(axB=axB, F_Hz = F_Hz) as bode:
153        bode(sys=SPOFF['P.out', 'P.in'], label='P to P')
154        bode(sys=SPOFF['P.out', 'S.in'], label='S to P')
155        bode(sys=SPOFF['S.out', 'S.in'], label='S to S', linestyle=':', linewidth=2)
156        bode(sys=S['S.out', 'S.in'], label='S to S (orig)', linestyle=':', linewidth=2)
157        bode(sys=SPOFF['T.out', 'O.in'], label='O to Meas. Out')
158        bode(sys=SPOFF['T.out', 'S.in'], label='S to Meas. Out')
159
160    axB.ax1.legend(fontsize=5)
161    axB.save(tjoin('SPOFF_bode.pdf'))
162    axB.save(tjoin('SPOFF_bode.png'))
163
164    #print('SPOFF', SPOFF.iod)
165    #print(SPOFF['T.out', 'S.in']._zp[1])
166
167    #truncate_inputs = ['P.in', 'S.in', 'O.in', 'T.in.1', 'T.in.2', 'FBNS.in', 'F2.in', 'Zinf.in']
168    #truncate_outputs = ['P.out', 'O.out', 'S.out', 'T.out', 'FBNS.out', 'F2.out']
169    #SPOFF = ssutil.truncate_io(SPOFF, truncate_inputs, truncate_outputs)
170
171    control.bode(SPOFF.mod[SPOFF.iod['F2.out'], SPOFF.iod['P.in']], dB=True, Hz=True, omega_limits=omega_limits, label='P to Flat FOM')
172    control.bode(SPOFF.mod[SPOFF.iod['FBNS.out'], SPOFF.iod['P.in']], dB=True, Hz=True, omega_limits=omega_limits, label='P to BNS FOM')
173    control.bode(SPOFF.mod[SPOFF.iod['P.out'], SPOFF.iod['S.in']], dB=True, Hz=True, omega_limits=omega_limits, label='S to P')
174    control.bode(SPOFF.mod[SPOFF.iod['S.out'], SPOFF.iod['S.in']], dB=True, Hz=True, omega_limits=omega_limits, label='S to S', linestyle='dotted', linewidth=4)
175    control.bode(SPOFF.mod[SPOFF.iod['T.out'], SPOFF.iod['O.in']], dB=True, Hz=True, omega_limits=omega_limits, label='O to Meas. Out')
176    control.bode(SPOFF.mod[SPOFF.iod['T.out'], SPOFF.iod['S.in']], dB=True, Hz=True, omega_limits=omega_limits, label='S to Meas. Out')
177    plt.legend(fontsize=5)
178    plt.savefig(tjoin('SPOFF_all_bode.pdf'))
179    plt.savefig(tjoin('SPOFF_all_bode.png'))
180    plt.close()
181
182    SPOFF_bal = ssutil.balance_sys_gain(SPOFF)
183
184    axFOM_S = ssutil.bode(SPOFF.siso('FBNS.out', 'FBNS.in'), omega_limits=omega_limits_fom, label='FBNS', color='red')
185    axFOM_S = ssutil.bode(SPOFF.siso(iodutil.listoutputs(FFlat)[0], iodutil.listinputs(FFlat)[0]), axB=axFOM_S, omega_limits=omega_limits_fom, label='FFlat', color='dodgerblue')
186    axFOM_S = ssutil.bode(SPOFF_bal.siso('FBNS.out', 'FBNS.in'), omega_limits=omega_limits_fom, axB=axFOM_S, label='FBNS SPOFF bal', color='green')
187    axFOM_S = ssutil.bode(SPOFF_bal.siso(iodutil.listoutputs(FFlat)[0], iodutil.listinputs(FFlat)[0]), axB=axFOM_S, omega_limits=omega_limits_fom, label='FFlat SPOFF bal', color='green')
188    axFOM_S = ssutil.bode(FBNS.siso('FBNS.out', 'FBNS.in'), axB=axFOM_S, omega_limits=omega_limits_fom, label='FBNS orig.', linestyle='dotted', color='red', linewidth=4)
189    axFOM_S = ssutil.bode(FFlat.siso(iodutil.listoutputs(FFlat)[0], iodutil.listinputs(FFlat)[0]), axB=axFOM_S, omega_limits=omega_limits_fom, label='FFlat orig.', color='dodgerblue', linestyle='dotted', linewidth=4)
190    axFOM_S.save(tjoin('FOM_bode_from_SPOFF.pdf'))
191    axFOM_S.save(tjoin('FOM_bode_from_SPOFF.png'))
192
193    #SPOFF = ssutil.balance_sys_gain(SPOFF)
194
195    P_load2 = ssutil.loadSys(fjoin(folder, P_fname))
196    assert(np.allclose(P_load2.A, P.A))
197    assert(np.allclose(P_load2.B, P.B))
198    assert(np.allclose(P_load2.C, P.C))
199    assert(np.allclose(P_load2.D, P.D))
200
201    ssutil.savesys(SPOFF, tjoin('ADY_Sanex.mat'))
202    ssutil.savesys(P, tjoin('ADY_plant.mat'))
203
204    ssutil.savesys(SPOFF, fjoin(folder, 'ADY_Sanex.mat'))
205    ssutil.savesys(P, fjoin(folder, 'ADY_plant.mat'))
206
207    return
pytest information

This code is wrapped in a pytest function using conventions detailed in pytest_conventions. The full name of this test, as known by the documentation, is:

test.ASC_SOLVER.T_ADY_make_sys.test_Make_ADY

The full name is useful when building documentation, to link a reference to this page using :func:`name`, or directly include it with an autofunction directive. The collapse nodes below show every instance of the test run. There may only be one, but if the test was run multiple times through pytest parametrizations, the list can be longer.

test_Make_ADY[ExampleModels_newFOM_F3]
output
{'FBNS.in': 0, 'FBNS.out': 0, 'FBNS.DARM.out': 1}
FBNS scale 2.960593226947428e-11
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
The plant is stable and has no non-minphase zeros. This means that the plant is strictly proper and no adjustments need to be made to the plant
Adding F3 after the controller output
P' should be flat because of how it was constructed. Not adding P' to F3
F3 poles:  [-12566.37061436+0.00000000e+00j  -1256.63706144+1.84470726e-07j
  -1256.63706144-1.84470726e-07j   -181.60072098+2.77615779e-05j
   -181.60072098-2.77615779e-05j   -113.48687238+1.36190499e+02j
   -113.48687238-1.36190499e+02j   -113.49040983+1.36214122e+02j
   -113.49040983-1.36214122e+02j   -113.51048946+1.36186963e+02j
   -113.51048946-1.36186963e+02j   -113.51403078+1.36210579e+02j
   -113.51403078-1.36210579e+02j    -54.94582132+6.43809992e+00j
    -54.94582132-6.43809992e+00j    -55.53613297+5.09920472e+00j
    -55.53613297-5.09920472e+00j    -53.88160102+7.06211820e+00j
    -53.88160102-7.06211820e+00j    -54.95054365+3.20780445e+00j
    -54.95054365-3.20780445e+00j    -52.76652603+6.98932446e+00j
    -52.76652603-6.98932446e+00j    -51.92181189+6.33187146e+00j
    -51.92181189-6.33187146e+00j    -51.65851489+5.37273175e+00j
    -51.65851489-5.37273175e+00j    -51.659588  +4.50670881e+00j
    -51.659588  -4.50670881e+00j    -52.34223409+3.02722782e+00j
    -52.34223409-3.02722782e+00j    -36.19762324+7.51940781e-02j
    -36.19762324-7.51940781e-02j    -36.33045107+1.37453947e-01j
    -36.33045107-1.37453947e-01j    -36.43235831+5.62255577e-02j
    -36.43235831-5.62255577e-02j]
F3 zs:  [-12.74162146 +0.j         -28.96870337+15.01749344j
 -28.96870337-15.01749344j -62.09875771 +9.16044997j
 -62.09875771 -9.16044997j -54.01839166+16.05469555j
 -54.01839166-16.05469555j -30.58459061 +0.j
 -42.35683227+10.21345753j -42.35683227-10.21345753j
 -40.90782718 +0.j        ]
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
test_Make_ADY[ExampleModels]
output
['0j', '0j', '0j', '0j', '(-0+24.649822653310352j)', '(-0-24.649822653310352j)', '(-0+20.897110605542636j)', '(-0-20.897110605542636j)', '(-0+13.963002900860413j)', '(-0-13.963002900860413j)', '(-0+4.903154579458684j)', '(-0-4.903154579458684j)', '(-0+24.649822653310352j)', '(-0-24.649822653310352j)', '(-0+20.897110605542636j)', '(-0-20.897110605542636j)', '(-0+13.963002900860413j)', '(-0-13.963002900860413j)', '(-0+4.903154579458684j)', '(-0-4.903154579458684j)']
['0j', '0j', '0j', '0j', '(-0+24.649822653310352j)', '(-0-24.649822653310352j)', '(-0+20.897110605542636j)', '(-0-20.897110605542636j)', '(-0+13.963002900860413j)', '(-0-13.963002900860413j)', '(-0+4.903154579458684j)', '(-0-4.903154579458684j)', '(-0+24.649822653310352j)', '(-0-24.649822653310352j)', '(-0+20.897110605542636j)', '(-0-20.897110605542636j)', '(-0+13.963002900860413j)', '(-0-13.963002900860413j)', '(-0+4.903154579458684j)', '(-0-4.903154579458684j)']
['(-2178.2052157029675+0j)', '(-287.1654677213149+0j)', '(-1695.4502902414451+0j)', '(-12.88579675913225+5.603093166973548j)', '(-12.88579675913225-5.603093166973548j)', '(-12.890063158702414+5.596646900702218j)', '(-12.890063158702414-5.596646900702218j)', '(-12.890063158702372+5.596646900702337j)', '(-12.890063158702372-5.596646900702337j)', '(-12.890063158702388+5.5966469007023j)', '(-12.890063158702388-5.5966469007023j)', '(-12.890063158702446+5.596646900702153j)', '(-12.890063158702446-5.596646900702153j)', '(-12.89006315870248+5.5966469007020585j)', '(-12.89006315870248-5.5966469007020585j)', '(-12.890063158702388+5.596646900702294j)', '(-12.890063158702388-5.596646900702294j)', '(-12.894331029649276+5.590187234277706j)', '(-12.894331029649276-5.590187234277706j)', '(-41254.24545663495+74429.27280788597j)', '(-41254.24545663495-74429.27280788597j)', '(-393.2693078650807+641.5816869585774j)', '(-393.2693078650807-641.5816869585774j)', '(-270.2702244864787+531.5395656330295j)', '(-270.2702244864787-531.5395656330295j)', '(-0.1697459318944503+0.05397308658344683j)', '(-0.1697459318944503-0.05397308658344683j)', '(-0.17074996279987628+0.056468761593217655j)', '(-0.17074996279987628-0.056468761593217655j)', '(-0.35336968654430834+1.2037757200586874j)', '(-0.35336968654430834-1.2037757200586874j)', '(-0.3531584357281473+1.2030238621502156j)', '(-0.3531584357281473-1.2030238621502156j)', '(-0.06095148837221796+1.7758885072601485j)', '(-0.06095148837221796-1.7758885072601485j)', '(-0.07262696482159792+2.327687224237036j)', '(-0.07262696482159792-2.327687224237036j)', '(-82.12808426287661+279.8184014267577j)', '(-82.12808426287661-279.8184014267577j)', '(-12.890063158702372+5.596646900702337j)', '(-12.890063158702372-5.596646900702337j)']
<IPython.core.display.Markdown object>
{'FBNS.in': 0, 'FBNS.out': 0, 'FBNS.DARM.out': 1}
FBNS scale 6.75666824737328e-11
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
The plant is stable and has no non-minphase zeros. This means that the plant is strictly proper and no adjustments need to be made to the plant
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
test_Make_ADY[ExampleModels_newFOM]
output
{'FBNS.in': 0, 'FBNS.out': 0, 'FBNS.DARM.out': 1}
FBNS scale 2.960593226947428e-11
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
The plant is stable and has no non-minphase zeros. This means that the plant is strictly proper and no adjustments need to be made to the plant
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
test_Make_ADY[ExampleModels_working_F3]
output
['0j', '0j', '0j', '0j', '(-0+24.649822653310352j)', '(-0-24.649822653310352j)', '(-0+20.897110605542636j)', '(-0-20.897110605542636j)', '(-0+13.963002900860413j)', '(-0-13.963002900860413j)', '(-0+4.903154579458684j)', '(-0-4.903154579458684j)', '(-0+24.649822653310352j)', '(-0-24.649822653310352j)', '(-0+20.897110605542636j)', '(-0-20.897110605542636j)', '(-0+13.963002900860413j)', '(-0-13.963002900860413j)', '(-0+4.903154579458684j)', '(-0-4.903154579458684j)']
['0j', '0j', '0j', '0j', '(-0+24.649822653310352j)', '(-0-24.649822653310352j)', '(-0+20.897110605542636j)', '(-0-20.897110605542636j)', '(-0+13.963002900860413j)', '(-0-13.963002900860413j)', '(-0+4.903154579458684j)', '(-0-4.903154579458684j)', '(-0+24.649822653310352j)', '(-0-24.649822653310352j)', '(-0+20.897110605542636j)', '(-0-20.897110605542636j)', '(-0+13.963002900860413j)', '(-0-13.963002900860413j)', '(-0+4.903154579458684j)', '(-0-4.903154579458684j)']
['(-2178.2052157029675+0j)', '(-287.1654677213149+0j)', '(-1695.4502902414451+0j)', '(-12.88579675913225+5.603093166973548j)', '(-12.88579675913225-5.603093166973548j)', '(-12.890063158702414+5.596646900702218j)', '(-12.890063158702414-5.596646900702218j)', '(-12.890063158702372+5.596646900702337j)', '(-12.890063158702372-5.596646900702337j)', '(-12.890063158702388+5.5966469007023j)', '(-12.890063158702388-5.5966469007023j)', '(-12.890063158702446+5.596646900702153j)', '(-12.890063158702446-5.596646900702153j)', '(-12.89006315870248+5.5966469007020585j)', '(-12.89006315870248-5.5966469007020585j)', '(-12.890063158702388+5.596646900702294j)', '(-12.890063158702388-5.596646900702294j)', '(-12.894331029649276+5.590187234277706j)', '(-12.894331029649276-5.590187234277706j)', '(-41254.24545663495+74429.27280788597j)', '(-41254.24545663495-74429.27280788597j)', '(-393.2693078650807+641.5816869585774j)', '(-393.2693078650807-641.5816869585774j)', '(-270.2702244864787+531.5395656330295j)', '(-270.2702244864787-531.5395656330295j)', '(-0.1697459318944503+0.05397308658344683j)', '(-0.1697459318944503-0.05397308658344683j)', '(-0.17074996279987628+0.056468761593217655j)', '(-0.17074996279987628-0.056468761593217655j)', '(-0.35336968654430834+1.2037757200586874j)', '(-0.35336968654430834-1.2037757200586874j)', '(-0.3531584357281473+1.2030238621502156j)', '(-0.3531584357281473-1.2030238621502156j)', '(-0.06095148837221796+1.7758885072601485j)', '(-0.06095148837221796-1.7758885072601485j)', '(-0.07262696482159792+2.327687224237036j)', '(-0.07262696482159792-2.327687224237036j)', '(-82.12808426287661+279.8184014267577j)', '(-82.12808426287661-279.8184014267577j)', '(-12.890063158702372+5.596646900702337j)', '(-12.890063158702372-5.596646900702337j)']
<IPython.core.display.Markdown object>
{'FBNS.in': 0, 'FBNS.out': 0, 'FBNS.DARM.out': 1}
FBNS scale 6.75666824737328e-11
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
The plant is stable and has no non-minphase zeros. This means that the plant is strictly proper and no adjustments need to be made to the plant
Adding F3 after the controller output
P' should be flat because of how it was constructed. Not adding P' to F3
F3 poles:  [-1884.96062603+5.03382207e-03j -1884.96062603-5.03382207e-03j
 -1884.95055828+5.03381170e-03j -1884.95055828-5.03381170e-03j
  -251.4713905 +0.00000000e+00j  -251.32761439+1.44179064e-01j
  -251.32761439-1.44179064e-01j  -251.18302987+0.00000000e+00j
   -26.50982787+1.35534312e+02j   -26.50982787-1.35534312e+02j
   -26.50983071+1.35534309e+02j   -26.50983071-1.35534309e+02j
  -181.60120388+0.00000000e+00j  -181.60023809+0.00000000e+00j
   -75.49360653+1.14900461e+02j   -75.49360653-1.14900461e+02j
   -75.49360681+1.14900420e+02j   -75.49360681-1.14900420e+02j
  -133.27390798+2.69593748e+01j  -133.27390798-2.69593748e+01j
  -133.27391544+2.69595262e+01j  -133.27391544-2.69595262e+01j
  -112.98413676+7.67739813e+01j  -112.98413676-7.67739813e+01j
  -112.9841968 +7.67740581e+01j  -112.9841968 -7.67740581e+01j
  -113.49378922+1.36256844e+02j  -113.49378922-1.36256844e+02j
  -113.55678375+1.36207254e+02j  -113.55678375-1.36207254e+02j
  -113.44409521+1.36193909e+02j  -113.44409521-1.36193909e+02j
  -113.50713428+1.36144156e+02j  -113.50713428-1.36144156e+02j
   -36.38042509+0.00000000e+00j   -36.35021801+5.22021695e-02j
   -36.35021801-5.22021695e-02j   -36.29000833+5.20946300e-02j
   -36.29000833-5.20946300e-02j   -36.25998742+0.00000000e+00j]
F3 zs:  [ 4.40097619e+05+5.55982318e+06j  4.40097619e+05-5.55982318e+06j
 -8.80438686e+05+0.00000000e+00j -1.21634279e+02+2.88605968e+02j
 -1.21634279e+02-2.88605968e+02j -2.07484152e+02+2.07760403e+02j
 -2.07484152e+02-2.07760403e+02j -1.32793944e+02+1.33276157e+02j
 -1.32793944e+02-1.33276157e+02j -1.49205071e+02+1.07696061e+02j
 -1.49205071e+02-1.07696061e+02j -1.57549943e+01+2.52141418e+01j
 -1.57549943e+01-2.52141418e+01j -4.37167724e+01+1.81587255e+01j
 -4.37167724e+01-1.81587255e+01j -5.10799314e+01+6.05670239e+00j
 -5.10799314e+01-6.05670239e+00j -6.93637160e+01+0.00000000e+00j
 -1.12984167e+02+7.67740197e+01j -1.12984167e+02-7.67740197e+01j
 -2.65098293e+01+1.35534310e+02j -2.65098293e+01-1.35534310e+02j
 -2.51327407e+02+0.00000000e+00j -2.51327418e+02+0.00000000e+00j
 -1.33273912e+02+2.69594505e+01j -1.33273912e+02-2.69594505e+01j
 -7.54936067e+01+1.14900440e+02j -7.54936067e+01-1.14900440e+02j
 -2.65098293e+01+1.35534310e+02j -2.65098293e+01-1.35534310e+02j
 -1.88495559e+03+0.00000000e+00j -1.88495559e+03+0.00000000e+00j
 -1.12984167e+02+7.67740197e+01j -1.12984167e+02-7.67740197e+01j
 -7.54936067e+01+1.14900440e+02j -7.54936067e+01-1.14900440e+02j
 -2.51327407e+02+0.00000000e+00j -2.51327418e+02+0.00000000e+00j
  0.00000000e+00+0.00000000e+00j]
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
test_Make_ADY[ExampleModels_working]
output
['0j', '0j', '0j', '0j', '(-0+24.649822653310352j)', '(-0-24.649822653310352j)', '(-0+20.897110605542636j)', '(-0-20.897110605542636j)', '(-0+13.963002900860413j)', '(-0-13.963002900860413j)', '(-0+4.903154579458684j)', '(-0-4.903154579458684j)', '(-0+24.649822653310352j)', '(-0-24.649822653310352j)', '(-0+20.897110605542636j)', '(-0-20.897110605542636j)', '(-0+13.963002900860413j)', '(-0-13.963002900860413j)', '(-0+4.903154579458684j)', '(-0-4.903154579458684j)']
['0j', '0j', '0j', '0j', '(-0+24.649822653310352j)', '(-0-24.649822653310352j)', '(-0+20.897110605542636j)', '(-0-20.897110605542636j)', '(-0+13.963002900860413j)', '(-0-13.963002900860413j)', '(-0+4.903154579458684j)', '(-0-4.903154579458684j)', '(-0+24.649822653310352j)', '(-0-24.649822653310352j)', '(-0+20.897110605542636j)', '(-0-20.897110605542636j)', '(-0+13.963002900860413j)', '(-0-13.963002900860413j)', '(-0+4.903154579458684j)', '(-0-4.903154579458684j)']
['(-2178.2052157029675+0j)', '(-287.1654677213149+0j)', '(-1695.4502902414451+0j)', '(-12.88579675913225+5.603093166973548j)', '(-12.88579675913225-5.603093166973548j)', '(-12.890063158702414+5.596646900702218j)', '(-12.890063158702414-5.596646900702218j)', '(-12.890063158702372+5.596646900702337j)', '(-12.890063158702372-5.596646900702337j)', '(-12.890063158702388+5.5966469007023j)', '(-12.890063158702388-5.5966469007023j)', '(-12.890063158702446+5.596646900702153j)', '(-12.890063158702446-5.596646900702153j)', '(-12.89006315870248+5.5966469007020585j)', '(-12.89006315870248-5.5966469007020585j)', '(-12.890063158702388+5.596646900702294j)', '(-12.890063158702388-5.596646900702294j)', '(-12.894331029649276+5.590187234277706j)', '(-12.894331029649276-5.590187234277706j)', '(-41254.24545663495+74429.27280788597j)', '(-41254.24545663495-74429.27280788597j)', '(-393.2693078650807+641.5816869585774j)', '(-393.2693078650807-641.5816869585774j)', '(-270.2702244864787+531.5395656330295j)', '(-270.2702244864787-531.5395656330295j)', '(-0.1697459318944503+0.05397308658344683j)', '(-0.1697459318944503-0.05397308658344683j)', '(-0.17074996279987628+0.056468761593217655j)', '(-0.17074996279987628-0.056468761593217655j)', '(-0.35336968654430834+1.2037757200586874j)', '(-0.35336968654430834-1.2037757200586874j)', '(-0.3531584357281473+1.2030238621502156j)', '(-0.3531584357281473-1.2030238621502156j)', '(-0.06095148837221796+1.7758885072601485j)', '(-0.06095148837221796-1.7758885072601485j)', '(-0.07262696482159792+2.327687224237036j)', '(-0.07262696482159792-2.327687224237036j)', '(-82.12808426287661+279.8184014267577j)', '(-82.12808426287661-279.8184014267577j)', '(-12.890063158702372+5.596646900702337j)', '(-12.890063158702372-5.596646900702337j)']
<IPython.core.display.Markdown object>
{'FBNS.in': 0, 'FBNS.out': 0, 'FBNS.DARM.out': 1}
FBNS scale 6.75666824737328e-11
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
The plant is stable and has no non-minphase zeros. This means that the plant is strictly proper and no adjustments need to be made to the plant
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
test_Make_ADY[ExampleModels_DARMFOM]
output
{'FBNS.in': 0, 'FBNS.out': 0, 'FBNS.DARM.out': 1}
FBNS scale 8.646766852528927e-11
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
The plant is stable and has no non-minphase zeros. This means that the plant is strictly proper and no adjustments need to be made to the plant
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
<IPython.core.display.Markdown object>
transposeSys(sys, FOM_ns)[source]

This is a pytest needing documentation

code
 1def transposeSys(sys, FOM_ns):
 2    # add Z_inf as an input
 3    sys_inf_in_badname = ssutil.duplicate_io(sys, 'T.in.1')
 4    sys_inf_in = ssutil.rename_io(sys_inf_in_badname, 'T.in.1.2', 'Zinf.in')
 5    #print(sys.iod)
 6
 7    inputs= ['D.in', 'O.in', 'S.in', 'Zinf.in']
 8    outputs_no_inf = [fns + '.out' for fns in FOM_ns] + ['T.out']
 9
10    sys_red = ssutil.truncate_io(sys_inf_in, inputs, outputs_no_inf)
11
12    # Transpose the system
13    sys_transpose = ssutil.transpose(sys_red)
14
15    # Reorder the inputs and outputs
16    sys_transpose = ssutil.reorder_io(sys_transpose, 
17        [fns + '.in' for fns in FOM_ns] + ['T.in'], [
18        'Zinf.out',
19        'S.out',
20        'O.out',
21        'D.out'
22    ])
23
24    return sys_transpose
pytest information

This code is wrapped in a pytest function using conventions detailed in pytest_conventions. The full name of this test, as known by the documentation, is:

test.ASC_SOLVER.T_ADY_make_sys.transposeSys

The full name is useful when building documentation, to link a reference to this page using :func:`name`, or directly include it with an autofunction directive. The collapse nodes below show every instance of the test run. There may only be one, but if the test was run multiple times through pytest parametrizations, the list can be longer.

ws_tf2ss(z, p, k, gain=1, mfactor=1, angular=True)[source]

Takes a python control zpk and returns a python control statespace. Uses more numerically stable wield computations to convert between.

code
docstring
"""
Takes a python control zpk and returns a python control statespace.
Uses more numerically stable wield computations to convert between.
"""
1def ws_tf2ss(z, p, k, gain=1, mfactor=1, angular=True):
2
3    ws_zpk = SISO.zpk(z, p, k * gain, angular=True, fiducial_rtol=1e-5, fiducial_atol=1e-10)
4    ws_SS = ws_zpk.asSS * mfactor
5    # print("ZPK: ", ws_SS.asZPK.z, ws_SS.asZPK.p)
6
7    # return control.ss(ws_SS.A.T, ws_SS.C.T, ws_SS.B.T, ws_SS.D.T)
8    return control.ss(ws_SS.A, ws_SS.B, ws_SS.C, ws_SS.D)
pytest information

This code is wrapped in a pytest function using conventions detailed in pytest_conventions. The full name of this test, as known by the documentation, is:

test.ASC_SOLVER.T_ADY_make_sys.ws_tf2ss

The full name is useful when building documentation, to link a reference to this page using :func:`name`, or directly include it with an autofunction directive. The collapse nodes below show every instance of the test run. There may only be one, but if the test was run multiple times through pytest parametrizations, the list can be longer.