T_ADY_make_paper¶
test.ASC_SOLVER_PAPER.T_ADY_make_paper
This File has the sole purpose of creating the ASC DHARD Y Model that is then exported to the buzz repository.
Functions
|
|
|
|
|
This is a pytest needing documentation |
|
This is a pytest needing documentation |
|
Create a state space model for an adder. |
|
sys should be a wield.control.SISO object |
|
This is a pytest needing documentation |
|
Create a state space model for the delay block. |
|
Plot multiple bode plots at once. |
|
Create a state space model for the null block. |
|
This is the main function that is called to create the model for the ASC DHARD Y. |
|
This is a pytest needing documentation |
|
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_paper/BNS_FOM_from_DARM.yml')) 8 # BNS_zpk = file_io.load(fjoin('ExampleModels_paper/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_PAPER.T_ADY_make_paper.FBNSSS_DARMThe 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_PAPER.T_ADY_make_paper.FBNSSS_HandThe 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_PAPER.T_ADY_make_paper.FBNSsimpSSThe 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_PAPER.T_ADY_make_paper.FFlatSSThe 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:
- 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_PAPER.T_ADY_make_paper.addSSThe 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_PAPER.T_ADY_make_paper.bodeThe 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_PAPER.T_ADY_make_paper.delayDriveThe 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_PAPER.T_ADY_make_paper.delaySSThe 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:
- 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_PAPER.T_ADY_make_paper.nullSSThe 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_paper' 4 ] 5) 6@pytest.mark.gitlabCI 7@pytest.mark.ADY 8def test_Make_ADY(folder): 9 10 S = ssutil.loadSys(fjoin(folder, 'ADY_E_from_fit.mat')) 11 O = ssutil.loadSys(fjoin(folder, 'ADY_M_from_fit.mat')) 12 P_fname = 'ADY_plant_from_fit.mat' 13 P = ssutil.loadSys(fjoin(folder, P_fname)) 14 15 # w2_rescale = 2e5 16 w2_rescale = 1e6 17 S = (w2_rescale * S.siso('S.out', 'S.in')).mimo('S.out', 'S.in') 18 O = (w2_rescale * O.siso('O.out', 'O.in')).mimo('O.out', 'O.in') 19 20 if '_newFOM' in folder or '_newFOM_F3' in folder: 21 FBNS_func = FBNSSS_Hand 22 FBNS = FBNS_func() 23 FBNS_scale = FBNS_func(return_scale=True) 24 elif '_paper' in folder: 25 FBNS_func = FBNSSS_DARM 26 FBNS = FBNS_func() 27 FBNS_scale = FBNS_func(return_scale=True) 28 else: 29 FBNS_func = FBNSsimpSS 30 FBNS = FBNS_func() 31 FBNS_scale = FBNS_func(return_scale=True) 32 33 omega_limits=[1e-2, 1e4] 34 axB = ssutil.bode(FBNS.siso('FBNS.out', 'FBNS.in'), omega_limits=omega_limits, label='Simple FBNS') 35 axB = ssutil.bode(FBNSSS_Hand().siso('FBNS.out', 'FBNS.in'), omega_limits=omega_limits, axB=axB, label='Hand Fit FBNS') 36 37 axB.save(tjoin('BNS_FOMS_Comp.pdf')) 38 axB.save(tjoin('BNS_FOMS_Comp.png')) 39 40 FFlat = FFlatSS() 41 42 # Inject the coupling into the BNS FOM, normalize it to Hinf=1 and then collect its scale 43 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 44 FBNS = ssutil.multiconnect([Coup, FBNS], [['FBNS.in', 'COUP.out']]) 45 # FBNS = ssutil.truncate_io(FBNS, ['COUP.in'], ['FBNS.out']) #commented out to display DARM Spectrum 46 FBNS = ssutil.rename_io(FBNS, 'COUP.out', 'FBNS.DARM.out') # to see DARM Spectrum 47 FBNS = ssutil.rename_io(FBNS, 'COUP.in', 'FBNS.in') 48 49 FBNS_Trash, Coup_scale = ssutil.normalize_gain(ssutil.truncate_io(FBNS, ['FBNS.in'], ['FBNS.out']), norm=1, return_scale=True, method='fq_resp') 50 del FBNS_Trash 51 FBNS = ssutil.scale_io(FBNS, 'FBNS.out', Coup_scale) # using this to scale preserves the DARM.out output 52 53 FBNS_scale = FBNS_scale * Coup_scale 54 np.savetxt(fjoin(folder, 'FBNS_scale.txt'), [FBNS_scale]) 55 print('FBNS scale', FBNS_scale) 56 57 current_range = np.loadtxt(fjoin(folder, 'FBNS_Current_range.txt')) # Saved by the normalization in the make function 58 io_scales = Bunch( 59 FBNS = FBNS_scale, # will need to apply this to the BNS FOM 60 w2_rescale = w2_rescale, # will need to divide by this on both FOMs 61 # will need to be applied only to the Flat fom since the A2L_coupling_with_cal includes it as a factor 62 ct2rad = 5.2e-11, # Calibration from https://alog.ligo-wa.caltech.edu/aLOG/index.php?callRep=69551 63 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 64 current_range = current_range, 65 ) 66 io_scales.RMS_cal_F1 = 1/io_scales.FBNS * io_scales.strain2m / io_scales.w2_rescale 67 io_scales.RMS_cal_F2 = io_scales.ct2rad / io_scales.w2_rescale 68 file_io.save(fjoin(folder, 'io_scales.yml'), dict(io_scales)) 69 70 omega_limits=[1e-2, 1e4] 71 72 omega_limits_noise = [1e-1, 1e3] 73 axN = ssutil.bode(ssutil.asSISO(S), omega_limits=omega_limits_noise, label='Seismic') 74 axN = ssutil.bode(ssutil.asSISO(O), axB=axN, omega_limits=omega_limits_noise, label='Meas. Noise') 75 axN = ssutil.bode(ssutil.asSISO(P), axB=axN, omega_limits=omega_limits_noise, label='Plant') 76 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') 77 axN.save(tjoin('Noise_bode.png')) 78 axN.save(tjoin('Noise_bode.pdf')) 79 80 81 # control.bode(S.mod, dB=False, Hz=True, omega_limits=omega_limits, label='Seismic') 82 # control.bode(O.mod, dB=False, Hz=True, omega_limits=omega_limits, label='Meas. Noise') 83 # control.bode(P.mod, dB=False, Hz=True, omega_limits=omega_limits, label='Plant') 84 # 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') 85 # plt.legend() 86 # plt.savefig(tjoin('Noise_bode.pdf'), bbox_inches='tight') 87 # plt.savefig(tjoin('Noise_bode.png'), bbox_inches='tight', dpi=300) 88 # plt.close() 89 90 omega_limits_fom = np.array([1e-1, 1e5])*2*np.pi 91 axFOM = ssutil.bode(FBNS.siso('FBNS.out', 'FBNS.in'), omega_limits=omega_limits_fom, label='FBNS') 92 axFOM = ssutil.bode(FFlat.siso(iodutil.listoutputs(FFlat)[0], iodutil.listinputs(FFlat)[0]), axB=axFOM, omega_limits=omega_limits_fom, label='FFlat') 93 axFOM.save(tjoin('FOM_bode.pdf')) 94 axFOM.save(tjoin('FOM_bode.png')) 95 # control.bode(FBNS.mod, dB=True, Hz=True, omega_limits=omega_limits, label='FBNS') 96 # control.bode(FFlat.mod, dB=True, Hz=True, omega_limits=omega_limits, label='FFlat') 97 # plt.legend() 98 # plt.savefig(tjoin('FOM_bode.pdf')) 99 # plt.savefig(tjoin('FOM_bode.png')) 100 # plt.close() 101 102 #make the SO 103 #conlist =[['T_SO.in.1', 'O.out'], ['T_SO.in.2','S.out']] 104 #T_SO = addSS(namespace='T_SO', sub=True) 105 #SO = ssutil.multiconnect([S, O, T_SO], conlist) 106 #SO = ssutil.truncate_io(SO, ['O.in', 'S.in'], ['T_SO.out', 'S.out']) 107 #SO = ssutil.rename_io(SO, 'T_SO.out', 'O.out') 108 109 #control.bode(SO.mod[SO.iod['S.out'], SO.iod['S.in']], dB=True, Hz=True, omega_limits=omega_limits, label='S to S') 110 #control.bode(SO.mod[SO.iod['O.out'], SO.iod['O.in']], dB=True, Hz=True, omega_limits=omega_limits, label='O to O') 111 #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) 112 #control.bode(S.mod, dB=True, Hz=True, omega_limits=[1e-2, 1e3], label='Orig. S', linestyle='dotted', linewidth=4) 113 #control.bode(O.mod, dB=True, Hz=True, omega_limits=[1e-2, 1e3], label='Orig. O', linestyle='dotted', linewidth=4) 114 #plt.legend(fontsize=8) 115 #plt.savefig(tjoin('SO_bode.pdf')) 116 #plt.close() 117 if '_F3' in folder: 118 extras = 'F3_withP' 119 else: 120 extras = None 121 122 SPOFF = ssutil.makeSPOFF(S, P, O, FBNS, FFlat, diagnostic=True, extras=extras, balance=True) 123 #print('SPOFF', SPOFF.iod) 124 #SPOFF = ssutil.balance_sys_gain(SPOFF) 125 omega_limits=[1e-2, 1e3] 126 127 axB = mplfigB(Nrows=2) 128 F_Hz = np.geomspace(1e-2, 20, 1000) 129 with multi_bode(axB=axB, F_Hz = F_Hz) as bode: 130 bode(P['P.out', 'P.in'], label='P alone', linewidth=2, color='dodgerblue') 131 bode(SPOFF['P.out', 'P.in'], label='P to P in SPOFF', color='orange') 132 bode(SPOFF['P.out', 'S.in'], label='S to P', color='green') 133 bode(SPOFF['S.out', 'S.in'], label='S to S', linestyle='dotted', linewidth=4, color='green') 134 bode(SPOFF['P.out', 'SA.in'], linestyle='--', label='P Recombined', linewidth=4, color='dodgerblue') 135 bode(SPOFF['S.out', 'SA.in'], label='P that moved to S', color='dodgerblue', linestyle='dotted', linewidth=6) 136 bode(SPOFF['G.out', 'S.in'], label='Orig. S (from SPOFF)', color='red') 137 bode(S['S.out', 'S.in'], label='Orig. S alone', linestyle='dotted', linewidth=4, color='red') 138 axB.ax1.legend(fontsize=5) 139 axB.save(tjoin('SPOFF_diagnostic_bode.pdf')) 140 axB.save(tjoin('SPOFF_diagnostic_bode.png')) 141 142 axB = mplfigB(Nrows=2) 143 F_Hz = np.geomspace(1e-2, 20, 1000) 144 with multi_bode(axB=axB, F_Hz = F_Hz) as bode: 145 bode(sys=SPOFF['P.out', 'P.in'], label='P to P') 146 bode(sys=SPOFF['P.out', 'S.in'], label='S to P') 147 bode(sys=SPOFF['S.out', 'S.in'], label='S to S', linestyle=':', linewidth=2) 148 bode(sys=S['S.out', 'S.in'], label='S to S (orig)', linestyle=':', linewidth=2) 149 bode(sys=SPOFF['T.out', 'O.in'], label='O to Meas. Out') 150 bode(sys=SPOFF['T.out', 'S.in'], label='S to Meas. Out') 151 152 axB.ax1.legend(fontsize=5) 153 axB.save(tjoin('SPOFF_bode.pdf')) 154 axB.save(tjoin('SPOFF_bode.png')) 155 156 #print('SPOFF', SPOFF.iod) 157 #print(SPOFF['T.out', 'S.in']._zp[1]) 158 159 #truncate_inputs = ['P.in', 'S.in', 'O.in', 'T.in.1', 'T.in.2', 'FBNS.in', 'F2.in', 'Zinf.in'] 160 #truncate_outputs = ['P.out', 'O.out', 'S.out', 'T.out', 'FBNS.out', 'F2.out'] 161 #SPOFF = ssutil.truncate_io(SPOFF, truncate_inputs, truncate_outputs) 162 163 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') 164 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') 165 control.bode(SPOFF.mod[SPOFF.iod['P.out'], SPOFF.iod['S.in']], dB=True, Hz=True, omega_limits=omega_limits, label='S to P') 166 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) 167 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') 168 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') 169 plt.legend(fontsize=5) 170 plt.savefig(tjoin('SPOFF_all_bode.pdf')) 171 plt.savefig(tjoin('SPOFF_all_bode.png')) 172 plt.close() 173 174 SPOFF_bal = ssutil.balance_sys_gain(SPOFF) 175 176 axFOM_S = ssutil.bode(SPOFF.siso('FBNS.out', 'FBNS.in'), omega_limits=omega_limits_fom, label='FBNS', color='red') 177 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') 178 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') 179 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') 180 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) 181 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) 182 axFOM_S.save(tjoin('FOM_bode_from_SPOFF.pdf')) 183 axFOM_S.save(tjoin('FOM_bode_from_SPOFF.png')) 184 185 #SPOFF = ssutil.balance_sys_gain(SPOFF) 186 187 P_load2 = ssutil.loadSys(fjoin(folder, P_fname)) 188 assert(np.allclose(P_load2.A, P.A)) 189 assert(np.allclose(P_load2.B, P.B)) 190 assert(np.allclose(P_load2.C, P.C)) 191 assert(np.allclose(P_load2.D, P.D)) 192 193 ssutil.savesys(SPOFF, tjoin('ADY_Sanex.mat')) 194 ssutil.savesys(P, tjoin('ADY_plant.mat')) 195 196 ssutil.savesys(SPOFF, fjoin(folder, 'ADY_Sanex.mat')) 197 ssutil.savesys(P, fjoin(folder, 'ADY_plant.mat')) 198 199 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_PAPER.T_ADY_make_paper.test_Make_ADYThe 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_paper]
output
status: failed duration: 0.620s captured errors: folder = 'ExampleModels_paper' @pytest.mark.parametrize( 'folder', [ 'ExampleModels_paper' ] ) @pytest.mark.gitlabCI @pytest.mark.ADY def test_Make_ADY(folder): """ This is the main function that is called to create the model for the ASC DHARD Y. """ S = ssutil.loadSys(fjoin(folder, 'ADY_E_from_fit.mat')) O = ssutil.loadSys(fjoin(folder, 'ADY_M_from_fit.mat')) P_fname = 'ADY_plant_from_fit.mat' P = ssutil.loadSys(fjoin(folder, P_fname)) # w2_rescale = 2e5 w2_rescale = 1e6 S = (w2_rescale * S.siso('S.out', 'S.in')).mimo('S.out', 'S.in') O = (w2_rescale * O.siso('O.out', 'O.in')).mimo('O.out', 'O.in') if '_newFOM' in folder or '_newFOM_F3' in folder: FBNS_func = FBNSSS_Hand FBNS = FBNS_func() FBNS_scale = FBNS_func(return_scale=True) elif '_paper' in folder: FBNS_func = FBNSSS_DARM FBNS = FBNS_func() FBNS_scale = FBNS_func(return_scale=True) else: FBNS_func = FBNSsimpSS FBNS = FBNS_func() FBNS_scale = FBNS_func(return_scale=True) omega_limits=[1e-2, 1e4] axB = ssutil.bode(FBNS.siso('FBNS.out', 'FBNS.in'), omega_limits=omega_limits, label='Simple FBNS') axB = ssutil.bode(FBNSSS_Hand().siso('FBNS.out', 'FBNS.in'), omega_limits=omega_limits, axB=axB, label='Hand Fit FBNS') axB.save(tjoin('BNS_FOMS_Comp.pdf')) axB.save(tjoin('BNS_FOMS_Comp.png')) FFlat = FFlatSS() # Inject the coupling into the BNS FOM, normalize it to Hinf=1 and then collect its scale 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 > FBNS = ssutil.multiconnect([Coup, FBNS], [['FBNS.in', 'COUP.out']]) /builds/buzz/test/ASC_SOLVER_PAPER/T_ADY_make_paper.py:447: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ sysList = [MIMOStateSpace with inputs ['COUP.in'], outputs ['COUP.out'], and 16 dimensional states, MIMOStateSpace with inputs ['FBNS.in'], outputs ['FBNS.out'], and 45 dimensional states] conlist = [['FBNS.in', 'COUP.out']], dictList = None, balance = False concentrate = False def multiconnect(sysList: list, conlist, dictList=None, balance=False, concentrate=False): """Connect a list of systems together. This is a wrapper for the control.connect function. This function also appends input output dictionaries together. Args: sysList (list): A list of systems or of Bunch objects including dictionaries. conlist (list): A list of connections. This is a list of lists of the form [[input1, output1], [input2, output2]]. The inputs and outputs can be either strings or integers. If they are strings, they must be in the input output dictionary of one of the models. dictList (list, optional): A list of dictionaries. Defaults to None. balance (bool, optional): Whether to balance the gain of each individual system using the balance_sys_gain() function. Defaults to True. Returns: Bunch: Bunch with mod and iod as attributes """ # TODO, this should only balance on IO that is used in the conlist # if balance: # sysList = [sys.balance() for sys in sysList] if balance: sysList = [balance_sys_gain(sys) for sys in sysList] # the [::-1] reverses the connections, which preserves them being upper-triangular given # the conventions of the connection list # this is largely unnecessary since topological_sort is called now > sys = MIMO.ssjoinsum(*sysList[::-1], _cls=ss.MIMOStateSpace) E TypeError: ssjoinsum() got an unexpected keyword argument '_cls' /builds/buzz/src/buzz/ssutil.py:340: TypeError
- 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_PAPER.T_ADY_make_paper.transposeSysThe 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_PAPER.T_ADY_make_paper.ws_tf2ssThe 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.