Exemplo n.º 1
0
 def test_hvgate(self):
     """
     Test `andes.core.discrete.HVGate`
     """
     self.hv = HVGate(self.u1, self.u2)
     self.hv.sl.list2array(self.n)
     self.hv.sl.check_var()
     np.testing.assert_almost_equal(self.hv.sl.s0, np.array([1, 1, 1, 0, 0]))
     np.testing.assert_almost_equal(self.hv.sl.s1, np.array([0, 0, 1, 1, 1]))
Exemplo n.º 2
0
    def __init__(self, system, config):
        ExcBase.__init__(self, system, config)
        ExcVsum.__init__(self)

        self.UEL0.v_str = '-999'
        self.OEL0.v_str = '999'

        self.flags.nr_iter = True

        # NOTE: e_str `KC*XadIfd / INT_y - IN` causes numerical inaccuracies
        self.IN = Algeb(tex_name='I_N',
                        info='Input to FEX',
                        v_str='1',
                        v_iter='KC * XadIfd - INT_y * IN',
                        e_str='ue * (KC * XadIfd - INT_y * IN)',
                        diag_eps=True,
                        )

        self.FEX = Piecewise(u=self.IN,
                             points=(0, 0.433, 0.75, 1),
                             funs=('1', '1 - 0.577*IN', 'sqrt(0.75 - IN ** 2)', '1.732*(1 - IN)', 0),
                             info='Piecewise function FEX',
                             )
        self.FEX.y.v_str = '1'
        self.FEX.y.v_iter = self.FEX.y.e_str

        # control block begin
        self.LG = Lag(self.v, T=self.TR, K=1,
                      info='Voltage transducer',
                      )

        # input excitation voltages;
        self.vi = Algeb(info='Total input voltages',
                        tex_name='V_i',
                        unit='p.u.',
                        e_str='ue * (-LG_y + vref + UEL + OEL + Vs - vi)',
                        v_str='-v + vref',
                        diag_eps=True,
                        )

        self.LL = LeadLag(u=self.vi, T1=self.TC, T2=self.TB,
                          info='V_A, Lead-lag compensator',
                          zero_out=True,
                          )  # LL_y == VA

        self.VAMAXu = ConstService('VAMAX * ue + (1-ue) * 999')
        self.VAMINu = ConstService('VAMIN * ue + (1-ue) * -999')

        self.LA = LagAntiWindup(u=self.LL_y,
                                T=self.TA,
                                K=self.KA,
                                upper=self.VAMAXu,
                                lower=self.VAMINu,
                                info='V_A, Anti-windup lag',
                                )  # LA_y == VA

        self.HVG = HVGate(u1=self.UEL,
                          u2=self.LA_y,
                          info='HVGate for under excitation',
                          )

        self.LVG = LVGate(u1=self.HVG_y,
                          u2=self.OEL,
                          info='HVGate for under excitation',
                          )

        self.INTin = 'ue * (LVG_y - VFE)'

        ExcACSat.__init__(self)

        self.vref.v_str = 'v + VFE / KA'

        self.vref0 = PostInitService(info='Initial reference voltage input',
                                     tex_name='V_{ref0}',
                                     v_str='vref',
                                     )

        self.WF = Washout(u=self.VFE,
                          T=self.TF,
                          K=self.KF,
                          info='Stablizing circuit feedback',
                          )

        self.vout.e_str = 'ue * FEX_y * INT_y - vout'
Exemplo n.º 3
0
    def __init__(self, system, config):
        ExcBase.__init__(self, system, config)

        self.KPC = ConstService(v_str='KP * exp(1j * radians(THETAP))',
                                tex_name='K_{PC}',
                                info='KP polar THETAP',
                                vtype=np.complex)

        # vd, vq, Id, Iq from SynGen
        self.vd = ExtAlgeb(
            src='vd',
            model='SynGen',
            indexer=self.syn,
            tex_name=r'V_d',
            info='d-axis machine voltage',
        )
        self.vq = ExtAlgeb(
            src='vq',
            model='SynGen',
            indexer=self.syn,
            tex_name=r'V_q',
            info='q-axis machine voltage',
        )
        self.Id = ExtAlgeb(
            src='Id',
            model='SynGen',
            indexer=self.syn,
            tex_name=r'I_d',
            info='d-axis machine current',
        )

        self.Iq = ExtAlgeb(
            src='Iq',
            model='SynGen',
            indexer=self.syn,
            tex_name=r'I_q',
            info='q-axis machine current',
        )

        # control block begin
        self.LG = Lag(
            self.v,
            T=self.TR,
            K=1,
            info='Voltage transducer',
        )

        self.UEL = Algeb(info='Interface var for under exc. limiter',
                         tex_name='U_{EL}',
                         v_str='0',
                         e_str='0 - UEL')

        self.VE = VarService(
            tex_name='V_E',
            info='VE',
            v_str='Abs(KPC*(vd + 1j*vq) + 1j*(KI + KPC*XL)*(Id + 1j*Iq))',
        )

        self.IN = Algeb(
            tex_name='I_N',
            info='Input to FEX',
            v_str='KC * XadIfd / VE',
            e_str='KC * XadIfd / VE - IN',
        )

        self.FEX = Piecewise(
            u=self.IN,
            points=(0, 0.433, 0.75, 1),
            funs=('1', '1 - 0.577*IN', 'sqrt(0.75 - IN ** 2)',
                  '1.732*(1 - IN)', 0),
            info='Piecewise function FEX',
        )

        self.VBMIN = dummify(-9999)
        self.VGMIN = dummify(-9999)

        self.VB = GainLimiter(
            u='VE*FEX_y',
            K=1,
            upper=self.VBMAX,
            lower=self.VBMIN,
            no_lower=True,
            info='VB with limiter',
        )

        self.VG = GainLimiter(
            u=self.vout,
            K=self.KG,
            upper=self.VGMAX,
            lower=self.VGMIN,
            no_lower=True,
            info='Feedback gain with HL',
        )

        self.vrs = Algeb(
            tex_name='V_{RS}',
            info='VR subtract feedback VG',
            v_str='vf0 / VB_y / KM',
            e_str='LAW1_y - VG_y - vrs',
        )

        self.vref = Algeb(
            info='Reference voltage input',
            tex_name='V_{ref}',
            unit='p.u.',
            v_str='(vrs + VG_y) / KA + v',
            e_str='vref0 - vref',
        )

        self.vref0 = PostInitService(
            info='Initial reference voltage input',
            tex_name='V_{ref0}',
            v_str='vref',
        )

        # input excitation voltages; PSS outputs summed at vi
        self.vi = Algeb(
            info='Total input voltages',
            tex_name='V_i',
            unit='p.u.',
            e_str='-LG_y + vref - vi',
            v_str='-v + vref',
        )

        self.vil = Algeb(info='Input voltage after limit',
                         tex_name='V_{il}',
                         v_str='HLI_zi*vi + HLI_zl*VIMIN + HLI_zu*VIMAX',
                         e_str='HLI_zi*vi + HLI_zl*VIMIN + HLI_zu*VIMAX - vil')

        self.HG = HVGate(
            u1=self.UEL,
            u2=self.vil,
            info='HVGate for under excitation',
        )

        self.LL = LeadLag(
            u=self.HG_y,
            T1=self.TC,
            T2=self.TB,
            info='Regulator',
            zero_out=True,
        )  # LL_y == VA

        self.LAW1 = LagAntiWindup(
            u=self.LL_y,
            T=self.TA,
            K=self.KA,
            lower=self.VRMIN,
            upper=self.VRMAX,
            info='Lag AW on VR',
        )  # LAW1_y == VR

        self.HLI = HardLimiter(
            u=self.vi,
            lower=self.VIMIN,
            upper=self.VIMAX,
            info='Input limiter',
        )

        self.LAW2 = LagAntiWindup(
            u=self.vrs,
            T=self.TM,
            K=self.KM,
            lower=self.VMMIN,
            upper=self.VMMAX,
            info='Lag AW on VM',
        )  # LAW2_y == VM

        self.vout.e_str = 'VB_y * LAW2_y - vout'
Exemplo n.º 4
0
    def __init__(self, system, config):
        ExcBase.__init__(self, system, config)

        # Set VRMAX to 999 when VRMAX = 0
        self._zVRM = FlagValue(
            self.VRMAX,
            value=0,
            tex_name='z_{VRMAX}',
        )
        self.VRMAXc = ConstService(
            v_str='VRMAX + 999*(1-_zVRM)',
            info='Set VRMAX=999 when zero',
        )
        self.LG = Lag(
            u=self.v,
            T=self.TR,
            K=1,
            info='Transducer delay',
        )

        self.SAT = ExcQuadSat(
            self.E1,
            self.SE1,
            self.E2,
            self.SE2,
            info='Field voltage saturation',
        )

        self.Se0 = ConstService(
            tex_name='S_{e0}',
            v_str='(vf0>SAT_A) * SAT_B*(SAT_A-vf0) ** 2 / vf0',
        )

        self.vfe0 = ConstService(
            v_str='vf0 * (KE + Se0)',
            tex_name='V_{FE0}',
        )
        self.vref0 = ConstService(
            info='Initial reference voltage input',
            tex_name='V_{ref0}',
            v_str='v + vfe0 / KA',
        )

        self.vref = Algeb(info='Reference voltage input',
                          tex_name='V_{ref}',
                          unit='p.u.',
                          v_str='vref0',
                          e_str='vref0 - vref')

        self.vi = Algeb(
            info='Total input voltages',
            tex_name='V_i',
            unit='p.u.',
            v_str='vref0 - v',
            e_str='(vref - v - WF_y) - vi',
        )

        self.LL = LeadLag(
            u=self.vi,
            T1=self.TC,
            T2=self.TB,
            info='Lead-lag compensator',
            zero_out=True,
        )

        self.UEL = Algeb(info='Interface var for under exc. limiter',
                         tex_name='U_{EL}',
                         v_str='0',
                         e_str='0 - UEL')

        self.HG = HVGate(
            u1=self.UEL,
            u2=self.LL_y,
            info='HVGate for under excitation',
        )

        self.VRU = VarService(
            v_str='VRMAXc * v',
            tex_name='V_T V_{RMAX}',
        )
        self.VRL = VarService(
            v_str='VRMIN * v',
            tex_name='V_T V_{RMIN}',
        )

        # TODO: WARNING: HVGate is temporarily skipped
        self.LA = LagAntiWindup(
            u=self.LL_y,
            T=self.TA,
            K=self.KA,
            upper=self.VRU,
            lower=self.VRL,
            info='Anti-windup lag',
        )  # LA_y == VR

        # `LessThan` may be causing memory issue in (SL_z0 * vout) - uncertain yet
        self.SL = LessThan(u=self.vout,
                           bound=self.SAT_A,
                           equal=False,
                           enable=True,
                           cache=False)

        self.Se = Algeb(
            tex_name=r"S_e(|V_{out}|)",
            info='saturation output',
            v_str='Se0',
            e_str='SL_z0 * (INT_y - SAT_A) ** 2 * SAT_B / INT_y - Se',
        )

        self.VFE = Algeb(info='Combined saturation feedback',
                         tex_name='V_{FE}',
                         unit='p.u.',
                         v_str='vfe0',
                         e_str='INT_y * (KE + Se) - VFE')

        self.INT = Integrator(
            u='LA_y - VFE',
            T=self.TE,
            K=1,
            y0=self.vf0,
            info='Integrator',
        )

        self.WF = Washout(u=self.INT_y,
                          T=self.TF1,
                          K=self.KF,
                          info='Feedback to input')

        self.vout.e_str = 'INT_y - vout'
Exemplo n.º 5
0
    def __init__(self, system, config):
        ExcBase.__init__(self, system, config)
        self.flags.nr_iter = True

        ExcVsum.__init__(self)
        self.UEL0.v_str = '-999'
        self.OEL0.v_str = '999'

        self.ulim = ConstService('9999')
        self.llim = ConstService('-9999')

        self.SWUEL = Switcher(u=self.UELc,
                              options=[0, 1, 2, 3],
                              tex_name='SW_{UEL}',
                              cache=True)
        self.SWVOS = Switcher(u=self.VOSc,
                              options=[0, 1, 2],
                              tex_name='SW_{VOS}',
                              cache=True)

        # control block begin
        self.LG = Lag(
            self.v,
            T=self.TR,
            K=1,
            info='Voltage transducer',
        )
        self.SG0 = ConstService(v_str='0', info='SG initial value.')
        self.SG = Algeb(
            tex_name='SG',
            info='SG',
            v_str='SG0',
            e_str='SG0 - SG',
        )

        self.zero = ConstService('0')
        self.LR = GainLimiter(
            u='XadIfd - ILR',
            K=self.KLR,
            R=1,
            upper=self.ulim,
            lower=self.zero,
            no_upper=True,
            info='Exciter output current gain limiter',
        )

        self.VA0 = PostInitService(tex_name='V_{A0}',
                                   v_str='vf0 - SWVOS_s2 * SG + LR_y',
                                   info='VA (LA_y) initial value')

        self.vref.v_str = 'ue * (v + (vf0 - SWVOS_s2 * SG + LR_y) / KA - SWVOS_s1 * SG - SWUEL_s1 * UEL)'
        self.vref.v_iter = 'ue * (v + (vf0 - SWVOS_s2 * SG + LR_y) / KA - SWVOS_s1 * SG - SWUEL_s1 * UEL)'

        self.vref0 = PostInitService(
            info='Initial reference voltage input',
            tex_name='V_{ref0}',
            v_str='vref',
        )

        self.vi = Algeb(
            info='Total input voltages',
            tex_name='V_i',
            unit='p.u.',
            e_str=
            'ue * (-LG_y + vref - WF_y + SWUEL_s1 * UEL + SWVOS_s1 * SG + Vs) - vi',
            v_iter=
            'ue * (-LG_y + vref - WF_y + SWUEL_s1 * UEL + SWVOS_s1 * SG + Vs)',
            v_str=
            'ue * (-LG_y + vref - WF_y + SWUEL_s1 * UEL + SWVOS_s1 * SG + Vs)',
        )

        self.vil = GainLimiter(
            u=self.vi,
            K=1,
            R=1,
            upper=self.VIMAX,
            lower=self.VIMIN,
            info='Exciter voltage input limiter',
        )

        self.UEL2 = Algeb(
            tex_name='UEL_2',
            info='UEL_2 as HVG1 u1',
            v_str='ue * (SWUEL_s2 * UEL + (1 - SWUEL_s2) * llim)',
            e_str='ue * (SWUEL_s2 * UEL + (1 - SWUEL_s2) * llim) - UEL2',
        )
        self.HVG1 = HVGate(
            u1=self.UEL2,
            u2=self.vil_y,
            info='HVGate after V_I',
        )

        self.LL = LeadLag(
            u=self.HVG1_y,
            T1=self.TC,
            T2=self.TB,
            info='Lead-lag compensator',
            zero_out=True,
        )

        self.LL1 = LeadLag(
            u=self.LL_y,
            T1=self.TC1,
            T2=self.TB1,
            info='Lead-lag compensator 1',
            zero_out=True,
        )

        self.LA = LagAntiWindup(
            u=self.LL1_y,
            T=self.TA,
            K=self.KA,
            upper=self.VAMAX,
            lower=self.VAMIN,
            info='V_A, Anti-windup lag',
        )  # LA_y is VA

        self.vas = Algeb(
            tex_name=r'V_{As}',
            info='V_A after subtraction, as HVG u2',
            v_str='ue * (SWVOS_s2 * SG + LA_y - LR_y)',
            v_iter='ue * (SWVOS_s2 * SG + LA_y - LR_y)',
            e_str='ue * (SWVOS_s2 * SG + LA_y - LR_y) - vas',
        )

        self.UEL3 = Algeb(
            tex_name='UEL_3',
            info='UEL_3 as HVG u1',
            v_str='ue * (SWUEL_s3 * UEL + (1 - SWUEL_s3) * llim)',
            e_str='ue * (SWUEL_s3 * UEL + (1 - SWUEL_s3) * llim) - UEL3',
        )
        self.HVG = HVGate(
            u1=self.UEL3,
            u2=self.vas,
            info='HVGate for under excitation',
        )

        self.LVG = LVGate(
            u1=self.HVG_y,
            u2=self.OEL,
            info='HVGate for over excitation',
        )

        # vd, vq, Id, Iq from SynGen
        self.vd = ExtAlgeb(
            src='vd',
            model='SynGen',
            indexer=self.syn,
            tex_name=r'V_d',
            info='d-axis machine voltage',
        )
        self.vq = ExtAlgeb(
            src='vq',
            model='SynGen',
            indexer=self.syn,
            tex_name=r'V_q',
            info='q-axis machine voltage',
        )

        self.efdu = VarService(
            info='Output exciter voltage upper bound',
            tex_name=r'efd_{u}',
            v_str='Abs(vd + 1j*vq) * VRMAX - KC * XadIfd',
        )
        self.efdl = VarService(info='Output exciter voltage lower bound',
                               tex_name=r'efd_{l}',
                               v_str='Abs(vd + 1j*vq) * VRMIN')

        self.vol = GainLimiter(
            u=self.LVG_y,
            K=1,
            R=1,
            upper=self.efdu,
            lower=self.efdl,
            info='Exciter output limiter',
        )

        self.WF = Washout(
            u=self.LVG_y,
            T=self.TF,
            K=self.KF,
            info='V_F, Stablizing circuit feedback',
        )

        self.vout.e_str = 'ue * vol_y  - vout'