def __init__(self, system, config): NodeData.__init__(self) Model.__init__(self, system=system, config=config) self.config.add(OrderedDict((('flat_start', 0), ))) self.config.add_extra( "_help", flat_start="flat start for voltages", ) self.config.add_extra( "_alt", flat_start=(0, 1), ) self.config.add_extra( "_tex", flat_start="z_{flat}", ) self.group = 'DCTopology' self.category = ['TransNode'] self.flags.update({'pflow': True}) self.v = Algeb( name='v', tex_name='V_{dc}', info='voltage magnitude', unit='p.u.', diag_eps=True, ) self.v.v_str = 'flat_start*1 + ' \ '(1-flat_start)*v0'
def __init__(self, system, config): TestFrame.__init__(self, system, config) self.uin = Algeb(v_str='-10', e_str='(dae_t - 10) - uin', tex_name='u_{in}') self.DB = DeadBand1(self.uin, center=0, lower=-5, upper=5)
def __init__(self): self.psid = Algeb( info='d-axis flux', tex_name=r'\psi_d', v_str='u * psid0', e_str='u * (ra * Iq + vq) - omega * psid', ) self.psiq = Algeb( info='q-axis flux', tex_name=r'\psi_q', v_str='u * psiq0', e_str='u * (ra * Id + vd) + omega * psiq', ) self.Id.e_str += '+ psid' self.Iq.e_str += '+ psiq'
def __init__(self, u, T1, T2, T3, T4, zero_out=False, name=None, tex_name=None, info=None): super(LeadLag2ndOrd, self).__init__(name=name, tex_name=tex_name, info=info) self.u = dummify(u) self.T1 = dummify(T1) self.T2 = dummify(T2) self.T3 = dummify(T3) self.T4 = dummify(T4) self.zero_out = zero_out self.enforce_tex_name((self.T1, self.T2, self.T3, self.T4)) self.x1 = State(info='State #1 in 2nd order lead-lag', tex_name="x'", t_const=self.T2) self.x2 = State(info='State #2 in 2nd order lead-lag', tex_name="x''") self.y = Algeb(info='Output of 2nd order lead-lag', tex_name='y', diag_eps=1e-6) self.vars = {'x1': self.x1, 'x2': self.x2, 'y': self.y} if self.zero_out is True: self.LT1 = LessThan(T1, dummify(0), equal=True, enable=zero_out, tex_name='LT', cache=True, z0=1, z1=0) self.LT2 = LessThan(T2, dummify(0), equal=True, enable=zero_out, tex_name='LT', cache=True, z0=1, z1=0) self.LT3 = LessThan(T4, dummify(0), equal=True, enable=zero_out, tex_name='LT', cache=True, z0=1, z1=0) self.LT4 = LessThan(T4, dummify(0), equal=True, enable=zero_out, tex_name='LT', cache=True, z0=1, z1=0) self.x2.discrete = (self.LT1, self.LT2, self.LT3, self.LT4) self.vars['LT1'] = self.LT1 self.vars['LT2'] = self.LT2 self.vars['LT3'] = self.LT3 self.vars['LT4'] = self.LT4
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): DC2Term.__init__(self, system, config) self.flags['pflow'] = True self.group = 'DCLink' self.R = NumParam( unit='p.u.', info='DC line resistance', non_zero=True, default=0.01, r=True, ) self.L = NumParam( unit='p.u.', info='DC line inductance', non_zero=True, default=0.001, r=True, ) self.IL = State( tex_name='I_L', info='Inductance current', unit='p.u.', e_str='u * (v1 - v2 - R * IL) / L', v_str='(v1 - v2) / R', ) self.Idc = Algeb( tex_name='I_{dc}', info='Current from node 2 to 1', unit='p.u.', e_str='-u * IL - Idc', v_str='-u * (v1 - v2) / R', ) self.v1.e_str = '-Idc' self.v2.e_str = '+Idc'
def setUp(self) -> None: self.n = 5 self.u1 = DummyValue(0) self.u1.v = np.zeros(self.n) self.u2 = Algeb(tex_name='u2') self.u2.v = np.array([-2, -1, 0, 1, 2])
def __init__(self, system, config): ACEData.__init__(self) Model.__init__(self, system, config) self.flags.tds = True self.config.add(OrderedDict([('freq_model', 'BusFreq')])) self.config.add_extra( '_help', {'freq_model': 'default freq. measurement model'}) self.config.add_extra('_alt', {'freq_model': ('BusFreq', )}) self.area = ExtParam(model='Bus', src='area', indexer=self.bus, export=False) self.busf.model = self.config.freq_model self.busfreq = DeviceFinder(self.busf, link=self.bus, idx_name='bus') self.f = ExtAlgeb( model='FreqMeasurement', src='f', indexer=self.busfreq, export=False, info='Bus frequency', ) self.ace = Algeb( info='area control error', unit='MW (p.u.)', tex_name='ace', e_str='10 * bias * (f - 1) - ace', )
def __init__(self, u, T1, T2, T3, T4, name=None, tex_name=None, info='2nd-order lead-lag'): super(LeadLag2ndOrd, self).__init__(name=name, tex_name=tex_name, info=info) self.u = u self.T1 = dummify(T1) self.T2 = dummify(T2) self.T3 = dummify(T3) self.T4 = dummify(T4) self.enforce_tex_name((self.T1, self.T2, self.T3, self.T4)) self.x1 = State(info='State #1 in 2nd order lead-lag', tex_name="x'", t_const=self.T2) self.x2 = State(info='State #2 in 2nd order lead-lag', tex_name="x''") self.y = Algeb(info='Output of 2nd order lead-lag', tex_name='y', diag_eps=1e-6) self.vars = {'x1': self.x1, 'x2': self.x2, 'y': self.y}
def __init__(self, system, config): ModelData.__init__(self) self.node = IdxParam( default=None, info='Node index', mandatory=True, model='Node', ) self.voltage = NumParam( default=0.0, tex_name='V_0', info='Ground voltage (typically 0)', unit='p.u.', ) Model.__init__(self, system, config) self.flags.update({'pflow': True}) self.group = 'DCLink' self.v = ExtAlgeb( model='Node', src='v', indexer=self.node, e_str='-Idc', ) self.Idc = Algeb( tex_name='I_{dc}', info='Ficticious current injection from ground', e_str='u * (v - voltage)', v_str='0', diag_eps=True, ) self.v.e_str = '-Idc'
def __init__(self, system, config): DC2Term.__init__(self, system, config) self.flags.pflow = True self.group = 'DCLink' self.C = NumParam( unit='p.u.', info='DC capacitance', non_zero=True, default=0.001, g=True, ) self.vC = State( tex_name='v_C', info='Capacitor current', unit='p.u.', v_str='0', e_str='-u * Idc / C', ) self.Idc = Algeb( tex_name='I_{dc}', info='Current from node 2 to 1', unit='p.u.', v_str='0', e_str='u * (vC - (v1 - v2)) + ' '(1 - u) * Idc', diag_eps=True, ) self.v1.e_str = '-Idc' self.v2.e_str = '+Idc'
def __init__(self, system=None, config=None): super().__init__(system, config) self.group = 'StaticGen' self.flags.update({'pflow': True, }) self.config.add(OrderedDict((('pv2pq', 0), ('npv2pq', 1)))) self.config.add_extra("_help", pv2pq="convert PV to PQ in PFlow at Q limits", npv2pq="max. # of pv2pq conversion in each iteration", ) self.config.add_extra("_alt", pv2pq=(0, 1), npv2pq=">=0" ) self.config.add_extra("_tex", pv2pq="z_{pv2pq}", npv2pq="n_{pv2pq}" ) self.a = ExtAlgeb(model='Bus', src='a', indexer=self.bus, tex_name=r'\theta') self.v = ExtAlgeb(model='Bus', src='v', indexer=self.bus, v_setter=True, tex_name=r'V') self.p = Algeb(info='actual active power generation', unit='p.u.', tex_name=r'p', diag_eps=1e-6) self.q = Algeb(info='actual reactive power generation', unit='p.u.', tex_name='q', diag_eps=1e-6) # TODO: implement switching starting from the second iteration # NOTE: TODO: PV to PQ conversion might not be fully working self.qlim = SortedLimiter(u=self.q, lower=self.qmin, upper=self.qmax, enable=self.config.pv2pq, n_select=self.config.npv2pq) # variable initialization equations self.v.v_str = 'v0' self.p.v_str = 'p0' self.q.v_str = 'q0' # injections into buses have negative values self.a.e_str = "-u * p" self.v.e_str = "-u * q" # power injection equations g(y) = 0 self.p.e_str = "u * (p0 - p)" self.q.e_str = "u*(qlim_zi * (v0-v) + "\ "qlim_zl * (qmin-q) + "\ "qlim_zu * (qmax-q))"
def __init__(self, system=None, config=None): BusData.__init__(self) Model.__init__(self, system=system, config=config) # island information self.n_islanded_buses = 0 self.islanded_buses = list() self.island_sets = list() self.islands = list() self.islanded_a = np.array([]) self.islanded_v = np.array([]) # config self.config.add(OrderedDict((('flat_start', 0), ))) self.config.add_extra("_help", flat_start="flat start for voltages", ) self.config.add_extra("_alt", flat_start=(0, 1), ) self.config.add_extra("_tex", flat_start="z_{flat}", ) self.group = 'ACTopology' self.category = ['TransNode'] self.flags.update({'collate': False, 'pflow': True}) self.a = Algeb(name='a', tex_name=r'\theta', info='voltage angle', unit='rad', ) self.v = Algeb(name='v', tex_name='V', info='voltage magnitude', unit='p.u.', ) # initial values self.a.v_str = 'flat_start*1e-8 + ' \ '(1-flat_start)*a0' self.v.v_str = 'flat_start*1 + ' \ '(1-flat_start)*v0'
def __init__(self, system, config): Model.__init__(self, system, config) self.flags.pflow = True self.flags.tds = True self.group = 'ACShort' self.a1 = ExtAlgeb(model='Bus', src='a', indexer=self.bus1, tex_name='a_1', info='phase angle of the from bus') self.a2 = ExtAlgeb(model='Bus', src='a', indexer=self.bus2, tex_name='a_2', info='phase angle of the to bus') self.v1 = ExtAlgeb(model='Bus', src='v', indexer=self.bus1, tex_name='v_1', info='voltage magnitude of the from bus') self.v2 = ExtAlgeb(model='Bus', src='v', indexer=self.bus2, tex_name='v_2', info='voltage magnitude of the to bus') self.p = Algeb( info='active power (1 to 2)', e_str='u * (a1 - a2)', tex_name='P', diag_eps=True, ) self.q = Algeb( info='active power (1 to 2)', e_str='u * (v1 - v2)', tex_name='Q', diag_eps=True, ) self.a1.e_str = 'p' self.a2.e_str = '-p' self.v1.e_str = 'q' self.v2.e_str = '-q'
def __init__(self, u, points: list, funs: list, name=None, tex_name=None, info=None): super().__init__(name=name, tex_name=tex_name, info=info) self.u = u self.points = points self.funs = funs self.y = Algeb(info='Output of piecewise function', tex_name='y') self.vars = {'y': self.y}
def __init__(self, u, K, name=None, tex_name=None, info=None): super().__init__(name=name, tex_name=tex_name, info=info) self.u = dummify(u) self.K = dummify(K) self.enforce_tex_name((self.K,)) self.y = Algeb(info='Gain output', tex_name='y') self.vars = {'y': self.y}
def setUp(self): self.lower = NumParam() self.upper = NumParam() self.u = Algeb() self.upper.v = np.array([2, 2, 2, 2, 2, 2, 2.8, 3.9]) self.u.v = np.array([-3, -1.1, -5, 0, 1, 2, 3, 10]) self.lower.v = np.array([-2, -1, 0.5, 0, 0.5, 1.5, 2, 3])
def __init__(self, u, T1, T2, lower, upper, name=None, tex_name=None, info=None): super().__init__(name=name, tex_name=tex_name, info=info) self.u = dummify(u) self.T1 = dummify(T1) self.T2 = dummify(T2) self.lower = lower self.upper = upper self.enforce_tex_name((self.T1, self.T2)) self.x = State(info='State in lead-lag TF', tex_name="x'", t_const=self.T2) self.ynl = Algeb(info='Output of lead-lag TF before limiter', tex_name=r'y_{nl}') self.y = Algeb(info='Output of lead-lag TF after limiter', tex_name=r'y', diag_eps=1e-6) self.lim = AntiWindup(u=self.ynl, lower=self.lower, upper=self.upper) self.vars = {'x': self.x, 'ynl': self.ynl, 'y': self.y, 'lim': self.lim}
def __init__(self, system=None, config=None): super().__init__(system, config) self.group = 'StaticGen' self.flags.update({'pflow': True, 'collate': True}) self.config.add(OrderedDict((('pv2pq', 0), ('npv2pq', 1)))) self.a = ExtAlgeb(model='Bus', src='a', indexer=self.bus, tex_name=r'\theta') self.v = ExtAlgeb(model='Bus', src='v', indexer=self.bus, v_setter=True, tex_name=r'V') self.p = Algeb(info='actual active power generation', unit='p.u.', tex_name=r'p', diag_eps=1e-6) self.q = Algeb(info='actual reactive power generation', unit='p.u.', tex_name='q', diag_eps=1e-6) # TODO: implement switching starting from the second iteration self.qlim = SortedLimiter(u=self.q, lower=self.qmin, upper=self.qmax, enable=self.config.pv2pq, n_select=self.config.npv2pq) # variable initialization equations self.v.v_str = 'v0' self.p.v_str = 'p0' self.q.v_str = 'q0' # injections into buses have negative values self.a.e_str = "-u * p" self.v.e_str = "-u * q" # power injection equations g(y) = 0 self.p.e_str = "u * (p0 - p)" self.q.e_str = "u * (qlim_zi * (v0 - v) + \
def __init__(self, system, config): ExcBase.__init__(self, system, config) ExcVsum.__init__(self) self.LP = Lag( u=self.v, T=self.TR, K=1, info='Voltage transducer', ) self.vi = Algeb( info='Total voltage input', unit='pu', e_str='ue * (-LP_y + vref + Vs - WF_y ) -vi ', v_str='ue*(-v +vref)', ) self.VRMAXu = ConstService('VRMAX * ue + (1-ue) * 999') self.VRMINu = ConstService('VRMIN * ue + (1-ue) * -999') self.VR = LagAntiWindup( u=self.vi, T=self.TA, K=self.KA, upper=self.VRMAXu, lower=self.VRMINu, ) self.LL = LeadLag( u=self.VR_y, T1=self.TF3, T2=self.TF2, ) self.WF = Washout(u=self.LL_y, T=self.TF1, K=self.KF) self.INTin = 'ue * (VR_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.VFE.v_str = "INT_y * KE + Se " self.VFE.e_str = "ue * (INT_y * KE + Se - VFE) " # disable iterative initialization of the integrator output self.INT.y.v_str = 'vf0' self.INT.y.v_iter = None self.vout.e_str = 'ue * INT_y - vout'
def __init__(self, system, config): Model.__init__(self, system, config) self.group = 'Experimental' self.flags.update({'tds': True}) self.uin = State( v_str=0, e_str= 'Piecewise((0, dae_t<= 0), (1, dae_t <= 2), (-1, dae_t <6), (1, True))', ) self.x = State( e_str='uin * Ki * HL_zi', v_str=0.05, ) self.y = Algeb(e_str='uin * Kp + x - y', v_str=0.05) self.HL = HardLimiter(u=self.y, lower=self.Wmin, upper=self.Wmax) self.w = Algeb(e_str='HL_zi * y + HL_zl * Wmin + HL_zu * Wmax - w', v_str=0.05)
def __init__(self, system, config): TGBase.__init__(self, system, config) self.pref = Algeb(info='Reference power input', tex_name='P_{ref}', v_str='tm0 * R', e_str='tm0 * R - pref', ) self.wd = Algeb(info='Generator under speed', unit='p.u.', tex_name=r'\omega_{dev}', v_str='0', e_str='u * (wref - omega) - wd', ) self.pd = Algeb(info='Pref plus under speed times gain', unit='p.u.', tex_name="P_d", v_str='tm0', e_str='(wd + pref) * gain - pd') self.LAG_x = State(info='State in lag transfer function', tex_name=r"x'_{LAG}", e_str='LAG_lim_zi * (1 * pd - LAG_x)', t_const=self.T1, v_str='pd', ) self.LAG_lim = AntiWindupLimiter(u=self.LAG_x, lower=self.VMIN, upper=self.VMAX, tex_name='lim_{lag}', ) self.LL_x = State(info='State in lead-lag transfer function', tex_name="x'_{LL}", v_str='LAG_x', e_str='(LAG_x - LL_x)', t_const=self.T3 ) self.LL_y = Algeb(info='Lead-lag Output', tex_name='y_{LL}', v_str='LAG_x', e_str='T2 / T3 * (LAG_x - LL_x) + LL_x - LL_y', ) self.pout.e_str = '(LL_y + Dt * wd) - pout'
def __init__(self, system, config): DC2Term.__init__(self, system, config) self.flags.pflow = True self.group = 'DCLink' self.R = NumParam( unit='p.u.', tex_name='R', info='DC line resistance', non_zero=True, default=0.01, r=True, ) self.L = NumParam( unit='p.u.', tex_name='L', info='DC line inductance', non_zero=True, default=0.001, r=True, ) self.C = NumParam( unit='p.u.', tex_name='C', info='DC capacitance', non_zero=True, default=0.001, g=True, ) self.IL = State( tex_name='I_L', info='Inductance current', unit='p.u.', v_str='0', e_str='u * vC', t_const=self.L, ) self.vC = State( tex_name='v_C', info='Capacitor current', unit='p.u.', e_str='-u * (Idc - vC/R - IL)', v_str='v1 - v2', t_const=self.C, ) self.Idc = Algeb( tex_name='I_{dc}', info='Current from node 2 to 1', unit='p.u.', e_str='u * (vC - (v1 - v2)) + ' '(1 - u) * Idc', v_str='-(v1 - v2) / R', diag_eps=True, ) self.v1.e_str = '-Idc' self.v2.e_str = '+Idc'
def __init__(self, u, T, K, name=None, tex_name=None, info=None): super().__init__(name=name, tex_name=tex_name, info=info) self.u = dummify(u) self.T = dummify(T) self.K = dummify(K) self.enforce_tex_name((self.K, self.T)) self.x = State(info='State in washout filter', tex_name="x'", t_const=self.T) self.y = Algeb(info='Output of washout filter', tex_name=r'y', diag_eps=1e-6) self.vars.update({'x': self.x, 'y': self.y})
def __init__(self, u, kp, ki, ks, lower, upper, no_lower=False, no_upper=False, ref=0.0, x0=0.0, name=None, tex_name=None, info=None): Block.__init__(self, name=name, tex_name=tex_name, info=info) self.u = dummify(u) self.kp = dummify(kp) self.ki = dummify(ki) self.ks = dummify(ks) self.lower = dummify(lower) self.upper = dummify(upper) self.ref = dummify(ref) self.x0 = dummify(x0) self.xi = State(info="Integrator output", tex_name='xi') self.ys = Algeb(info="PI summation before limit", tex_name='ys') self.lim = HardLimiter(u=self.ys, lower=self.lower, upper=self.upper, no_lower=no_lower, no_upper=no_upper, tex_name='lim') self.y = Algeb(info="PI output", discrete=self.lim, tex_name='y') self.vars = {'xi': self.xi, 'ys': self.ys, 'lim': self.lim, 'y': self.y}
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): TGBase.__init__(self, system, config) self.gain = ConstService( v_str='u/R', tex_name='G', ) self.pref = Algeb( info='Reference power input', tex_name='P_{ref}', v_str='tm0 * R', e_str='tm0 * R - pref', ) self.wd = Algeb( info='Generator under speed', unit='p.u.', tex_name=r'\omega_{dev}', v_str='0', e_str='(wref - omega) - wd', ) self.pd = Algeb(info='Pref plus under speed times gain', unit='p.u.', tex_name="P_d", v_str='u * tm0', e_str='u*(wd + pref + paux) * gain - pd') self.LAG = LagAntiWindup( u=self.pd, K=1, T=self.T1, lower=self.VMIN, upper=self.VMAX, ) self.LL = LeadLag( u=self.LAG_y, T1=self.T2, T2=self.T3, ) self.pout.e_str = '(LL_y + Dt * wd) - pout'
def __init__(self, u, T1, T2, name=None, info='Lead-lag transfer function', safe_div=True): super().__init__(name=name, info=info) self.T1 = T1 self.T2 = T2 self.u = u self.safe_div = safe_div # TODO: implement me self.enforce_tex_name((self.T1, self.T2)) self.x = State(info='State in lead-lag transfer function', tex_name="x'") self.y = Algeb(info='Output of lead-lag transfer function', tex_name=r'y') self.vars = {'x': self.x, 'y': self.y}
def __init__(self, u, ref, kp, ki, name=None, info=None): super().__init__(name=name, info=info) self.u = u self.ref = ref self.kp = kp self.ki = ki self.xi = State(info="Integration value of PI controller") self.y = Algeb(info="Output value") self.vars = {'xi': self.xi, 'y': self.y}
def __init__(self, u1, u2, name=None, tex_name=None, info=None): super().__init__(name=name, tex_name=tex_name, info=info) self.u1 = dummify(u1) self.u2 = dummify(u2) self.enforce_tex_name((u1, u2)) self.y = Algeb(info='LVGate output', tex_name='y') self.sl = Selector(self.u1, self.u2, fun=np.minimum.reduce, info='LVGate Selector', ) self.vars = {'y': self.y, 'sl': self.sl}