def __init__(self, system, config): AreaData.__init__(self) Model.__init__(self, system, config) self.group = 'Collection' self.flags.update({'pflow': True, 'tds': True}) self.Bus = BackRef() self.ACTopology = BackRef() # --------------------Experiment Zone-------------------- self.Vn = ExtParam(model='Bus', src='Vn', indexer=self.ACTopology, export=False) self.Vn_sum = NumReduce(u=self.Vn, fun=np.sum, ref=self.Bus) self.Vn_sum_rep = NumRepeat(u=self.Vn_sum, ref=self.Bus) self.a = ExtAlgeb(model='ACTopology', src='a', indexer=self.ACTopology, info='Bus voltage angle') self.v = ExtAlgeb(model='ACTopology', src='v', indexer=self.ACTopology, info='Bus voltage magnitude')
def __init__(self): super().__init__() self.common_params.extend(('syn',)) self.common_vars.extend(('vout', 'vi',)) self.VoltComp = BackRef() self.PSS = BackRef()
def __init__(self): super().__init__() self.common_params.extend(('Sn', 'Vn', 'fn', 'bus', 'M', 'D')) self.common_vars.extend(('omega', 'delta', 'tm', 'te', 'vf', 'XadIfd', 'vd', 'vq', 'Id', 'Iq', 'a', 'v')) self.TurbineGov = BackRef() self.Exciter = BackRef()
def __init__(self, system, config): AreaData.__init__(self) Model.__init__(self, system, config) self.group = 'Collection' self.flags.pflow = True self.flags.tds = True self.Bus = BackRef() self.ACTopology = BackRef()
def __init__(self): super().__init__() self.common_params.extend( ('Sn', 'Vn', 'fn', 'bus', 'M', 'D', 'subidx')) self.common_vars.extend(( 'omega', 'delta', )) self.idx_island = [] self.uid_island = [] self.delta_addr = [] self.TurbineGov = BackRef() self.Exciter = BackRef()
def __init__(self): super().__init__() self.common_params.extend( ('Sn', 'Vn', 'p0', 'q0', 'ra', 'xs', 'subidx')) self.common_vars.extend(('p', 'q', 'a', 'v')) self.SynGen = BackRef()
def __init__(self, system, config): Model.__init__(self, system, config) self.group = 'Calculation' self.flags.update({'tds': True}) self.SynGen = BackRef(info='Back reference to SynGen idx') self.SynGenIdx = RefFlatten(ref=self.SynGen) self.M = ExtParam( model='SynGen', src='M', indexer=self.SynGenIdx, export=False, info='Linearly stored SynGen.M', ) self.wgen = ExtState( model='SynGen', src='omega', indexer=self.SynGenIdx, tex_name=r'\omega_{gen}', info='Linearly stored SynGen.omega', ) self.agen = ExtState( model='SynGen', src='delta', indexer=self.SynGenIdx, tex_name=r'\delta_{gen}', info='Linearly stored SynGen.delta', ) self.d0 = ExtService( model='SynGen', src='delta', indexer=self.SynGenIdx, tex_name=r'\delta_{gen,0}', info='Linearly stored initial delta', ) self.a0 = ExtService( model='SynGen', src='omega', indexer=self.SynGenIdx, tex_name=r'\omega_{gen,0}', info='Linearly stored initial omega', ) self.Mt = NumReduce( u=self.M, tex_name='M_t', fun=np.sum, ref=self.SynGen, info='Summation of M by COI index', ) self.Mr = NumRepeat( u=self.Mt, tex_name='M_{tr}', ref=self.SynGen, info='Repeated summation of M', ) self.Mw = ConstService(tex_name='M_w', info='Inertia weights', v_str='M/Mr') self.d0w = ConstService(tex_name=r'\delta_{gen,0,w}', v_str='d0 * Mw', info='Linearly stored weighted delta') self.a0w = ConstService(tex_name=r'\omega_{gen,0,w}', v_str='a0 * Mw', info='Linearly stored weighted omega') self.d0a = NumReduce( u=self.d0w, tex_name=r'\delta_{gen,0,avg}', fun=np.sum, ref=self.SynGen, info='Average initial delta', cache=False, ) self.a0a = NumReduce( u=self.a0w, tex_name=r'\omega_{gen,0,avg}', fun=np.sum, ref=self.SynGen, info='Average initial omega', cache=False, ) self.pidx = IdxRepeat(u=self.idx, ref=self.SynGen, info='Repeated COI.idx') # Note: # Even if d(omega) /d (omega) = 1, it is still stored as a lambda function. # When no SynGen is referencing any COI, j_update will not be called, # and Jacobian will become singular. `diag_eps = True` needs to be used. # Note: # Do not assign `v_str=1` for `omega`. Otherwise, COIs with no connected generators will # fail to initialize. self.omega = Algeb( tex_name=r'\omega_{coi}', info='COI speed', v_str='a0a', v_setter=True, e_str='-omega', diag_eps=True, ) self.delta = Algeb( tex_name=r'\delta_{coi}', info='COI rotor angle', v_str='d0a', v_setter=True, e_str='-delta', diag_eps=True, ) # Note: # `omega_sub` or `delta_sub` must not provide `v_str`. # Otherwise, values will be incorrectly summed for `omega` and `delta`. self.omega_sub = ExtAlgeb( model='COI', src='omega', e_str='Mw * wgen', indexer=self.pidx, info='COI frequency contribution of each generator') self.delta_sub = ExtAlgeb( model='COI', src='delta', e_str='Mw * agen', indexer=self.pidx, info='COI angle contribution of each generator')
def __init__(self, system, config): Model.__init__(self, system, config) self.group = 'Exciter' self.flags.tds = True # Voltage compensator idx-es self.VoltComp = BackRef() # from synchronous generators, get u, Sn, Vn, bus; tm0; omega self.ug = ExtParam( src='u', model='SynGen', indexer=self.syn, tex_name='u_g', info='Generator online status', unit='bool', export=False, ) self.ue = ConstService( v_str='u * ug', info="effective online status", tex_name='u_e', ) self.Sn = ExtParam( src='Sn', model='SynGen', indexer=self.syn, tex_name='S_m', info='Rated power from generator', unit='MVA', export=False, ) self.Vn = ExtParam( src='Vn', model='SynGen', indexer=self.syn, tex_name='V_m', info='Rated voltage from generator', unit='kV', export=False, ) self.vf0 = ExtService(src='vf', model='SynGen', indexer=self.syn, tex_name='v_{f0}', info='Steady state excitation voltage') self.bus = ExtParam( src='bus', model='SynGen', indexer=self.syn, tex_name='bus', info='Bus idx of the generators', export=False, vtype=str, ) self.omega = ExtState( src='omega', model='SynGen', indexer=self.syn, tex_name=r'\omega', info='Generator speed', is_input=True, ) self.vf = ExtAlgeb( src='vf', model='SynGen', indexer=self.syn, tex_name=r'v_f', e_str='ue * (vout - vf0)', info='Excitation field voltage to generator', ename='vf', tex_ename='v_f', is_input=False, ) self.XadIfd = ExtAlgeb( src='XadIfd', model='SynGen', indexer=self.syn, tex_name=r'X_{ad}I_{fd}', info='Armature excitation current', is_input=True, ) # from bus, get a and v self.a = ExtAlgeb( model='Bus', src='a', indexer=self.bus, tex_name=r'\theta', info='Bus voltage phase angle', is_input=True, ) self.vbus = ExtAlgeb(model='Bus', src='v', indexer=self.bus, tex_name='V', info='Bus voltage magnitude', is_input=True) # `self.v` is actually `ETERM` in other software # TODO: # Preferably, its name needs to be changed to `eterm`. # That requires updates in equations of all exciters. self.v = Algeb( info='Input to exciter (bus v or Eterm)', tex_name='E_{term}', v_str='vbus', e_str='vbus - v', v_str_add=True, ) # output excitation voltage self.vout = Algeb( info='Exciter final output voltage', tex_name='v_{out}', v_str='ue * vf0', diag_eps=True, is_output=True, )
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.SynGen = BackRef() 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=True) self.q = Algeb(info='actual reactive power generation', unit='p.u.', tex_name='q', diag_eps=True) # NOTE: # PV to PQ conversion uses a simple logic which converts a number of `npv2pq` PVs # with the largest violation to PQ, starting from the first iteration. # Manual tweaking of `npv2pq` may be needed for cases to converge. # 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) + "\ "qlim_zl * (qmin-q) + "\ "qlim_zu * (qmax-q))"
def __init__(self, system=None, config=None): super().__init__(system, config) self.group = 'StaticGen' self.flags.pflow = True self.flags.tds = True self.flags.tds_init = False self.config.add( OrderedDict(( ('pv2pq', 0), ('npv2pq', 0), ('min_iter', 2), ('err_tol', 0.01), ('abs_violation', 1), ))) self.config.add_extra( "_help", pv2pq="convert PV to PQ in PFlow at Q limits", npv2pq="max. # of conversion each iteration, 0 - auto", min_iter="iteration number starting from which to enable switching", err_tol="iteration error below which to enable switching", abs_violation='use absolute (1) or relative (0) limit violation', ) self.config.add_extra( "_alt", pv2pq=(0, 1), npv2pq=">=0", min_iter='int', err_tol='float', abs_violation=(0, 1), ) self.config.add_extra("_tex", pv2pq="z_{pv2pq}", npv2pq="n_{pv2pq}", min_iter="sw_{iter}", err_tol=r"\epsilon_{tol}") self.SynGen = BackRef() 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=True) self.q = Algeb(info='actual reactive power generation', unit='p.u.', tex_name='q', diag_eps=True) self.qlim = SortedLimiter( u=self.q, lower=self.qmin, upper=self.qmax, enable=self.config.pv2pq, n_select=self.config.npv2pq, min_iter=self.config.min_iter, err_tol=self.config.err_tol, abs_violation=self.config.abs_violation, ) # 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))"