def __init__(self, system, config): PVD1Model.__init__(self, system, config) # --- Determine whether the energy storage is in charging or discharging mode --- self.LTN = LessThan(self.Ipout_y, 0.0) # --- Add integrator. Assume that state-of-charge is the initial condition --- self.pIG = Integrator( u='-LTN_z1*(v * Ipout_y)*EtaC - LTN_z0*(v * Ipout_y)/EtaD', T=self.Tf, K='sys_mva / 3600 / En', y0=self.SOCinit, check_init=False, ) # --- Add hard limiter for SOC --- self.SOClim = HardLimiter(u=self.pIG_y, lower=self.SOCmin, upper=self.SOCmax) # --- Add Ipmax, Ipmin, and Ipcmd --- self.Ipmax.v_str = '(1-SOClim_zl)*(SWPQ_s1 * ialim + SWPQ_s0 * sqrt(Ipmaxsq0))' self.Ipmax.e_str = '(1-SOClim_zl)*(SWPQ_s1 * ialim + SWPQ_s0 * sqrt(Ipmaxsq)) - Ipmax' self.Ipmin = Algeb( info='Minimum value of Ip', v_str= '-(1-SOClim_zu) * (SWPQ_s1 * ialim + SWPQ_s0 * sqrt(Ipmaxsq0))', e_str= '-(1-SOClim_zu) * (SWPQ_s1 * ialim + SWPQ_s0 * sqrt(Ipmaxsq)) - Ipmin', ) self.Ipcmd.lim.lower = self.Ipmin self.Ipcmd.y.deps = ['Ipmin']
def __init__(self, system, config): Model.__init__(self, system, config) self.flags.tds = True self.group = 'RenGovernor' self.reg = ExtParam(model='RenExciter', src='reg', indexer=self.ree, export=False, ) self.Sn = ExtParam(model='RenGen', src='Sn', indexer=self.reg, tex_name='S_n', export=False, ) self.wge = ExtAlgeb(model='RenExciter', src='wg', indexer=self.ree, export=False, e_str='-1.0 + s1_y', ename='wg', tex_ename=r'\omega_g', ) self.Pe = ExtAlgeb(model='RenGen', src='Pe', indexer=self.reg, export=False, info='Retrieved Pe of RenGen') self.Pe0 = ExtService(model='RenGen', src='Pe', indexer=self.reg, tex_name='P_{e0}', ) self.H2 = ConstService(v_str='2 * H', tex_name='2H') self.Pm = Algeb(tex_name='P_m', info='Mechanical power', e_str='Pe0 - Pm', v_str='Pe0', ) self.wr0 = Algeb(tex_name=r'\omega_{r0}', unit='p.u.', v_str='w0', e_str='w0 - wr0', info='speed set point', ) # `s1_y` is `w_m` self.s1 = Integrator(u='(Pm - Pe) / wge - D * (s1_y - wr0)', T=self.H2, K=1.0, y0='wr0', ) # make two alias states, `wt` and `wg`, pointing to `s1_y` self.wt = AliasState(self.s1_y, tex_name=r'\omega_t') self.wg = AliasState(self.s1_y, tex_name=r'\omega_g') self.s3_y = State(info='Unused state variable', tex_name='y_{s3}', ) self.Kshaft = ConstService(v_str='1.0', tex_name='K_{shaft}', info='Dummy Kshaft', )
def __init__(self): self.SAT = ExcQuadSat( self.E1, self.SE1, self.E2, self.SE2, info='Field voltage saturation', ) # Input (VR - VFE) self.INT = Integrator( u=self.INTin, T=self.TE, K=1, y0=0, info='V_E, integrator', ) self.INT.y.v_str = 0.1 self.INT.y.v_iter = 'INT_y * FEX_y - vf0' self.SL = LessThan(u=self.INT_y, bound=self.SAT_A, equal=False, enable=True, cache=False) self.Se = Algeb( tex_name=r"V_{out}*S_e(|V_{out}|)", info='saturation output', v_str='Indicator(INT_y > SAT_A) * SAT_B * (INT_y - SAT_A) ** 2', e_str='ue * (SL_z0 * (INT_y - SAT_A) ** 2 * SAT_B - Se)', diag_eps=True, ) self.VFE = Algeb( info='Combined saturation feedback', tex_name='V_{FE}', unit='p.u.', v_str='INT_y * KE + Se + XadIfd * KD', e_str='ue * (INT_y * KE + Se + XadIfd * KD - VFE)', diag_eps=True, )
def __init__(self, system, config): PVD1Model.__init__(self, system, config) self.pgen = Algeb(info='Real power output', v_str='v * Ipout_y', e_str='v*Ipout_y - pgen', tex_name='P_{gen}' ) # --- Add integrator. Assume that state-of-charge is the initial condition --- self.pIG = Integrator(u=self.pgen, T=self.Tf, K=1.0, y0=self.SOCinit) # --- Add hard limiter for SOC --- self.SOC = HardLimiter(u=self.pIG_y, lower=self.SOCmin, upper=self.SOCmax) # --- Add Ipmax and Ipcmd --- self.Ipmax.v_str = '(1-SOC_zl)*(SWPQ_s1 * ialim + SWPQ_s0 * sqrt(Ipmaxsq0))' self.Ipmax.e_str = '(1-SOC_zl)*(SWPQ_s1 * ialim + SWPQ_s0 * sqrt(Ipmaxsq)) - Ipmax' self.Ipcmd.lim.sign_lower = dummify(-1) self.Ipcmd.lim.lower = self.Ipmax
def __init__(self, system, config): PVD1Model.__init__(self, system, config) # --- Add integrator. Assume that state-of-charge is the initial condition --- self.pIG = Integrator( u='v * Ipout_y', T=self.Tf, K=1.0, y0=self.SOCinit, check_init=False, ) # --- Add hard limiter for SOC --- self.SOC = HardLimiter(u=self.pIG_y, lower=self.SOCmin, upper=self.SOCmax) # --- Add Ipmax and Ipcmd --- self.Ipmax.v_str = '(1-SOC_zl)*(SWPQ_s1 * ialim + SWPQ_s0 * sqrt(Ipmaxsq0))' self.Ipmax.e_str = '(1-SOC_zl)*(SWPQ_s1 * ialim + SWPQ_s0 * sqrt(Ipmaxsq)) - Ipmax' self.Ipcmd.lim.sign_lower = dummify(-1) self.Ipcmd.lim.lower = self.Ipmax
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', ) # Saturation self.SAT = ExcQuadSat( self.E1, self.SE1, self.E2, self.SE2, info='Field voltage saturation', ) self.Se0 = ConstService( info='Initial saturation output', tex_name='S_{e0}', v_str='Indicator(vf0>SAT_A) * SAT_B * (SAT_A - vf0) ** 2 / vf0', ) self.vr0 = ConstService(info='Initial vr', tex_name='V_{r0}', v_str='(KE + Se0) * vf0') self.vb0 = ConstService(info='Initial vb', tex_name='V_{b0}', v_str='vr0 / KA') self.vref0 = ConstService( info='Initial reference voltage input', tex_name='V_{ref0}', v_str='v + vb0', ) self.vfe0 = ConstService( v_str='vf0 * (KE + Se0)', tex_name='V_{FE0}', ) self.vref = Algeb(info='Reference voltage input', tex_name='V_{ref}', unit='p.u.', v_str='vref0', e_str='vref0 - vref') self.LG = Lag( u=self.v, T=self.TR, K=1, info='Sensing delay', ) 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.LA = LagAntiWindup( u='vi + WF_y', T=self.TA, K=self.KA, upper=self.VRMAXc, lower=self.VRMIN, info='Anti-windup lag', ) 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.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.WF = Washout(u=self.vout, T=self.TF, K=self.KF, info='Stablizing circuit feedback') self.vout.e_str = 'INT_y - vout'
def __init__(self, system, config): Model.__init__(self, system, config) self.flags.tds = True self.group = 'RenGovernor' self.reg = ExtParam( model='RenExciter', src='reg', indexer=self.ree, export=False, ) self.Sn = ExtParam( model='RenGen', src='Sn', indexer=self.reg, tex_name='S_n', export=False, ) self.wge = ExtAlgeb( model='RenExciter', src='wg', indexer=self.ree, export=False, e_str='-1.0 + s2_y', ename='wg', tex_ename=r'\omega_g', ) self.Pe = ExtAlgeb(model='RenGen', src='Pe', indexer=self.reg, export=False, info='Retrieved Pe of RenGen') self.Pe0 = ExtService( model='RenGen', src='Pe', indexer=self.reg, tex_name='P_{e0}', ) self.Ht2 = ConstService(v_str='2 * Ht', tex_name='2H_t') self.Hg2 = ConstService(v_str='2 * Hg', tex_name='2H_g') self.wr0 = Algeb( tex_name=r'\omega_{r0}', unit='p.u.', v_str='w0', e_str='w0 - wr0', info='speed set point', ) self.Pm = Algeb( tex_name='P_m', info='Mechanical power', e_str='Pe0 - Pm', v_str='Pe0', ) # `s1_y` is `wt` self.s1 = Integrator( u='(Pm / s1_y) - (Kshaft * s3_y ) - pd', T=self.Ht2, K=1.0, y0='wr0', ) self.wt = AliasState(self.s1_y, tex_name=r'\omega_t') # `s2_y` is `wg` self.s2 = Integrator( u='-(Pe / s2_y) + (Kshaft * s3_y ) + pd', T=self.Hg2, K=1.0, y0='wr0', ) self.wg = AliasState(self.s2_y, tex_name=r'\omega_g') # TODO: `s3_y` needs to be properly reinitialized with the new `wr0` self.s3 = Integrator( u='s1_y - s2_y', T=1.0, K=1.0, y0='Pe0 / wr0 / Kshaft', ) self.pd = Algeb( tex_name='P_d', info='Output after damping', v_str='0.0', e_str='Dshaft * (s1_y - s2_y) - pd', )
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'
def __init__(self, system, config): TGBase.__init__(self, system, config) self.VELMn = ConstService( v_str='-VELM', tex_name='-VELM', ) self.tr = ConstService( v_str='r * Tr', tex_name='r*Tr', ) self.gr = ConstService( v_str='1/r', tex_name='1/r', ) self.ratel = ConstService( v_str='- VELM - gr', tex_name='rate_l', ) self.rateu = ConstService( v_str='VELM - gr', tex_name='rate_u', ) self.q0 = ConstService( v_str='tm0 / At + qNL', tex_name='q_0', ) self.pref = Algeb( info='Reference power input', tex_name='P_{ref}', v_str='R * q0', e_str='R * q0 - pref', ) self.wd = Algeb( info='Generator speed deviation', unit='p.u.', tex_name=r'\omega_{dev}', v_str='0', e_str='ue * (omega - wref) - wd', ) self.pd = Algeb( info='Pref plus speed deviation times gain', unit='p.u.', tex_name="P_d", v_str='0', e_str='ue * (- wd + pref + paux - R * dg) - pd', ) self.LG = Lag( u=self.pd, K=1, T=self.Tf, info='filter after speed deviation (e)', ) self.gtpos = State(info='State in gate position (c)', unit='rad', v_str='q0', tex_name=r'\delta', e_str='LG_y') self.dgl = VarService( tex_name='dg_{lower}', info='dg lower limit', v_str='- VELM - gr * LG_y', ) self.dgu = VarService( tex_name='dg_{upper}', info='dg upper limit', v_str='VELM - gr * LG_y', ) self.dg_lim = AntiWindupRate( u=self.gtpos, lower=self.GMIN, upper=self.GMAX, rate_lower=self.dgl, rate_upper=self.dgu, tex_name='lim_{dg}', info='gate velocity and position limiter', ) self.dg = Algeb( info='desired gate (c)', unit='p.u.', tex_name="dg", v_str='q0', e_str='gtpos + gr * LG_y - dg', ) self.LAG = Lag( u=self.dg, K=1, T=self.Tg, info='gate opening (g)', ) self.h = Algeb( info='turbine head', unit='p.u.', tex_name="h", e_str='q_y**2 / LAG_y**2 - h', v_str='1', ) self.q = Integrator(u="1 - q_y**2 / LAG_y**2", T=self.Tw, K=1, y0='q0', check_init=False, info="turbine flow (q)") self.pout.e_str = 'ue * (At * h * (q_y - qNL) - Dt * wd * LAG_y) - pout'
def __init__(self, system, config): ExcBase.__init__(self, system, config) self.flags.nr_iter = True self.SAT = ExcQuadSat(self.E1, self.SE1, self.E2, self.SE2, info='Field voltage saturation', ) self.SL = LessThan(u=self.vout, bound=self.SAT_A, equal=False, enable=True, cache=False) self.Se0 = ConstService(info='Initial saturation output', tex_name='S_{e0}', v_str='Indicator(vf0>SAT_A) * SAT_B * (SAT_A - vf0) ** 2 / vf0', ) self.IN = Algeb(tex_name='I_N', info='Input to FEX', v_str='1', v_iter='KC * XadIfd - INT_y * IN', e_str='KC * XadIfd / INT_y - 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.FEX.y.v_iter = '1' self.FEX.y.v_iter = self.FEX.y.e_str self.LG = Lag(self.v, T=self.TR, K=1, info='Voltage transducer', ) self.vi = Algeb(info='Total input voltages', tex_name='V_i', unit='p.u.', e_str='-v + vref - WF_y - vi', v_str='-v + vref', ) self.LL = LeadLag(u=self.vi, T1=self.TC, T2=self.TB, info='Regulator', zero_out=True, ) self.LA = LagAntiWindup(u=self.LL_y, T=self.TA, K=self.KA, lower=self.VRMIN, upper=self.VRMAX, info='Lag AW on VR', ) self.INT = Integrator(u='LA_y - VFE', T=self.TE, K=1, y0=0, info='Integrator', ) self.INT.y.v_str = 0.1 self.INT.y.v_iter = 'INT_y * FEX_y - vf0' 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='INT_y * (KE + Se) + XadIfd * KD', e_str='INT_y * (KE + Se) + XadIfd * KD - VFE' ) self.vref = Algeb(info='Reference voltage input', tex_name='V_{ref}', unit='p.u.', v_str='v + VFE / KA', e_str='vref0 - vref', ) 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 = 'INT_y * FEX_y - vout'
def __init__(self, system, config): Model.__init__(self, system, config) self.flags.tds = True self.group = 'RenGovernor' self.reg = ExtParam( model='RenExciter', src='reg', indexer=self.ree, vtype=str, export=False, ) self.Sn = ExtParam( model='RenGen', src='Sn', indexer=self.reg, tex_name='S_n', export=False, ) self.wge = ExtAlgeb( model='RenExciter', src='wg', indexer=self.ree, export=False, e_str='-1.0 + s2_y', ename='wg', tex_ename=r'\omega_g', ) self.Pe = ExtAlgeb(model='RenGen', src='Pe', indexer=self.reg, export=False, info='Retrieved Pe of RenGen') self.Pe0 = ExtService( model='RenGen', src='Pe', indexer=self.reg, tex_name='P_{e0}', ) self.Ht2 = ConstService(v_str='2 * (Htfrac * H)', tex_name='2H_t') self.Hg2 = ConstService(v_str='2 * H * (1 - Htfrac)', tex_name='2H_g') # (2*pi*Freq1)**2 is considered in p.u., which is Freq1**2 here self.Kshaft = ConstService(v_str='Ht2 * Hg2 * 0.5 * Freq1 * Freq1 / H', tex_name='K_{shaft}') self.wr0 = Algeb( tex_name=r'\omega_{r0}', unit='p.u.', v_str='w0', e_str='w0 - wr0', info='speed set point', ) self.Pm = Algeb( tex_name='P_m', info='Mechanical power', e_str='Pe0 - Pm', v_str='Pe0', ) # `s1_y` is `wt` self.s1 = Integrator( u='(Pm / s1_y) - s3_y - pd', T=self.Ht2, K=1.0, y0='wr0', ) self.wt = AliasState(self.s1_y, tex_name=r'\omega_t') # `s2_y` is `wg` self.s2 = Integrator( u='-(Pe / s2_y) + s3_y - DAMP * (s2_y - w0) + pd', T=self.Hg2, K=1.0, y0='wr0', ) self.wg = AliasState(self.s2_y, tex_name=r'\omega_g') # `s3_y` gets reinitialized in `WTTQA1` self.s3 = Integrator( u='s1_y - s2_y', T=1.0, K=self.Kshaft, y0='Pe0 / wr0', ) self.pd = Algeb( tex_name='P_d', info='Output after damping', e_str='Dshaft * (s1_y - s2_y) - pd', v_str='0', )