def __init__(self, system=None, config=None): BusData.__init__(self) Model.__init__(self, system=system, config=config) self.config.add(OrderedDict((('flat_start', 0.0), ))) 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) # Notes: # TimeSeries model is not used in power flow for now self.flags.tds = True self.config.add(OrderedDict((('silent', 1), ))) self.config.add_extra( "_help", silent="suppress output messages if is not zero", ) self.config.add_extra( "_alt", silent=(0, 1), ) self.SW = Switcher( self.mode, options=(0, 1, 2), info='mode switcher', ) self._data = OrderedDict( ) # keys are the idx, and values are the dataframe
def __init__(self, system, config): ModelData.__init__(self) self.node = IdxParam( default=None, tex_name='node', 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=1e-6, ) self.v.e_str = '-Idc'
def list2array(self): """ Set internal storage for timeseries data. Open file and read data into internal storage. """ Model.list2array(self) # read and store data for ii in range(self.n): idx = self.idx.v[ii] path = self.path.v[ii] sheet = self.sheet.v[ii] try: df = pd.read_excel(path, sheet_name=sheet) except FileNotFoundError as e: logger.error('<%s idx=%s>: File not found: "%s"', self.class_name, idx, path) raise e except ValueError as e: logger.error('<%s idx=%s>: Sheet not found: "%s" in "%s"', self.class_name, idx, sheet, path) raise e for field in self.fields.v[ii]: if field not in df.columns: raise ValueError('Field {} not found in timeseries data'.format(field)) self._data[idx] = df
def __init__(self, system, config): TogglerData.__init__(self) Model.__init__(self, system, config) self.flags.update({'tds': True}) self.group = 'TimedEvent' self.t.callback = self._u_switch
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=1e-6, ) self.v.v_str = 'flat_start*1 + ' \ '(1-flat_start)*v0'
def __init__(self, system, config): OutputData.__init__(self) Model.__init__(self, system, config) self.group = 'OutputSelect' self.xidx = [] self.yidx = []
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, 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() # --------------------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, system, config): AreaData.__init__(self) Model.__init__(self, system, config) self.group = 'Collection' self.flags.update({'pflow': True, 'tds': True}) self.Bus = RefParam(export=False) self.ACTopology = RefParam(export=False) # --------------------Experiment Zone-------------------- self.Vn = ExtParam(model='Bus', src='Vn', indexer=self.ACTopology, export=False) self.Vn_sum = ReducerService(u=self.Vn, fun=np.sum, ref=self.Bus) self.Vn_sum_rep = RepeaterService(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, system, config): Model.__init__(self, system, config) self.group = 'DynLoad' self.flags.tds = True self.bus = ExtParam(model='PQ', src='bus', indexer=self.pq) self.p0 = ExtService( model='PQ', src='Ppf', indexer=self.pq, tex_name='P_0', ) self.q0 = ExtService( model='PQ', src='Qpf', indexer=self.pq, tex_name='Q_0', ) self.v0 = ExtService( model='Bus', src='v', indexer=self.bus, tex_name='V_0', ) self.busfreq = DeviceFinder( u=self.busf, link=self.bus, idx_name='bus', info='found idx of BusFreq', ) self.f = ExtAlgeb( model='FreqMeasurement', src='f', indexer=self.busfreq, tex_name='f', ) self.pv0 = ConstService(v_str='u * kp/100 * p0 / (v0) ** ap ') self.qv0 = ConstService(v_str='u * kq/100 * q0 / (v0) ** aq ') self.a = ExtAlgeb( model='Bus', src='a', indexer=self.bus, tex_name=r'\theta', e_str='pv0 * (v ** ap) * (f ** bp)', ) self.v = ExtAlgeb( model='Bus', src='v', indexer=self.bus, tex_name='V', e_str='qv0 * (v ** aq) * (f ** bq)', )
def __init__(self, system, config): Model.__init__(self, system, config) self.group = 'TurbineGov' self.flags.update({'tds': True}) 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.tm0 = ExtService(src='tm', model='SynGen', indexer=self.syn, tex_name=r'\tau_{m0}', info='Initial mechanical input') self.omega = ExtState(src='omega', model='SynGen', indexer=self.syn, tex_name=r'\omega', info='Generator speed', unit='p.u.') self.gain = ConstService( v_str='u / R', tex_name='G', ) self.tm = ExtAlgeb( src='tm', model='SynGen', indexer=self.syn, tex_name=r'\tau_m', e_str='u * (pout - tm0)', info='Mechanical power to generator', ) self.pout = Algeb( info='Turbine final output power', tex_name='P_{out}', v_str='tm0', ) self.wref = Algeb( info='Speed reference variable', tex_name=r'\omega_{ref}', v_str='wref0', e_str='wref0 - wref', )
def __init__(self, system, config): ModelData.__init__(self) self.bus = IdxParam( model='Bus', info="linked bus idx", mandatory=True, ) self.tf = TimerParam( info='Fault start time for the bus', mandatory=True, callback=self.apply_fault, ) self.tc = TimerParam( info='Fault end time for the bus', callback=self.clear_fault, ) self.xf = NumParam( info='Fault to ground impedance', default=1e-4, tex_name='x_f', ) self.rf = NumParam( info='Fault to ground resistance', default=0, tex_name='x_f', ) Model.__init__(self, system, config) self.flags.update({'tds': True}) self.group = 'TimedEvent' self.gf = ConstService( tex_name='g_{f}', v_str='re(1/(rf + 1j * xf))', ) self.bf = ConstService( tex_name='b_{f}', v_str='im(1/(rf + 1j * xf))', ) self.uf = ConstService( tex_name='u_f', v_str='0', ) self.a = ExtAlgeb( model='Bus', src='a', indexer=self.bus, tex_name=r'\theta', e_str='u * uf * (v ** 2 * gf)', ) self.v = ExtAlgeb( model='Bus', src='v', indexer=self.bus, tex_name=r'V', e_str='u * uf * (v ** 2 * bf)', ) self._vstore = np.array([])
def __init__(self, system, config): ToggleData.__init__(self) Model.__init__(self, system, config) self.flags.update({'tds': True}) self.group = 'TimedEvent' self.t.callback = self._u_switch self._init = False # very first initialization that stores `u` self._u = ConstService('1')
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, routine): """ Set values for the very first time step. """ Model.init(self, routine) self.apply_exact(np.array(self.system.TDS.config.t0)) logger.debug('<%s>: Initialization done', self.class_name)
def __init__(self, system, config): ModelData.__init__(self, three_params=False) self.field = DataParam(info='field name') self.comment = DataParam(info='information, comment, or anything') self.comment2 = DataParam(info='comment field 2') self.comment3 = DataParam(info='comment field 3') self.comment4 = DataParam(info='comment field 4') Model.__init__(self, system, config) self.group = 'Information'
def __init__(self, system=None, config=None): ShuntData.__init__(self) Model.__init__(self, system, config) self.group = 'StaticShunt' self.flags['pflow'] = True self.a = ExtAlgeb(model='Bus', src='a', indexer=self.bus, tex_name=r'\theta') self.v = ExtAlgeb(model='Bus', src='v', indexer=self.bus, tex_name=r'V') self.a.e_str = 'u * v**2 * g' self.v.e_str = '-u * v**2 * b'
def __init__(self, system=None, config=None): LineData.__init__(self) Model.__init__(self, system, config) self.group = 'ACLine' self.flags.pflow = True self.flags.tds = True 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.gh = ConstService(tex_name='g_h') self.bh = ConstService(tex_name='b_h') self.gk = ConstService(tex_name='g_k') self.bk = ConstService(tex_name='b_k') self.yh = ConstService(tex_name='y_h', vtype=np.complex) self.yk = ConstService(tex_name='y_k', vtype=np.complex) self.yhk = ConstService(tex_name='y_{hk}', vtype=np.complex) self.ghk = ConstService(tex_name='g_{hk}') self.bhk = ConstService(tex_name='b_{hk}') self.gh.v_str = 'g1 + 0.5 * g' self.bh.v_str = 'b1 + 0.5 * b' self.gk.v_str = 'g2 + 0.5 * g' self.bk.v_str = 'b2 + 0.5 * b' self.yh.v_str = 'u * (gh + 1j * bh)' self.yk.v_str = 'u * (gk + 1j * bk)' self.yhk.v_str = 'u/((r+1e-8) + 1j*(x+1e-8))' self.ghk.v_str = 're(yhk)' self.bhk.v_str = 'im(yhk)' self.a1.e_str = 'u * (v1 ** 2 * (gh + ghk) / tap ** 2 - \ v1 * v2 * (ghk * cos(a1 - a2 - phi) + \ bhk * sin(a1 - a2 - phi)) / tap)' self.v1.e_str = 'u * (-v1 ** 2 * (bh + bhk) / tap ** 2 - \ v1 * v2 * (ghk * sin(a1 - a2 - phi) - \ bhk * cos(a1 - a2 - phi)) / tap)' self.a2.e_str = 'u * (v2 ** 2 * (gh + ghk) - \ v1 * v2 * (ghk * cos(a1 - a2 - phi) - \ bhk * sin(a1 - a2 - phi)) / tap)' self.v2.e_str = 'u * (-v2 ** 2 * (bh + bhk) + \
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.island_sets = list() self.islanded_buses = list( ) # list of lists containing bus uid of islands self.islands = list() # same as the above 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', is_output=True, ) self.v = Algeb( name='v', tex_name='V', info='voltage magnitude', unit='p.u.', is_output=True, ) # 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.tds = True self.group = 'TimedEvent' self.SW = Switcher( u=self.method, options=('+', '-', '*', '/', '='), info='Switcher for alteration method', ) self.t.callback = self._alter_field
def __init__(self, system, config): ACEData.__init__(self) Model.__init__(self, system, config) self.flags.tds = True self.group = 'Calculation' self.config.add( OrderedDict([ ('freq_model', 'BusFreq'), ('interval', 4.0), ('offset', 0.0), ])) self.config.add_extra( '_help', { 'freq_model': 'default freq. measurement model', 'interval': 'sampling time interval', 'offset': 'sampling time offset' }) 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.fs = Sampling( self.f, interval=self.config.interval, offset=self.config.offset, tex_name='f_s', info='Sampled freq.', ) self.ace = Algeb( info='area control error', unit='MW (p.u.)', tex_name='ace', e_str='10 * bias * (fs_v - 1) - ace', )
def __init__(self, system, config): ModelData.__init__(self) self.node1 = IdxParam( default=None, tex_name='node_1', info='Node 1 index', mandatory=True, model='Node', ) self.node2 = IdxParam( default=None, tex_name='node_2', info='Node 2 index', mandatory=True, model='Node', ) self.Vdcn1 = NumParam( default=100, info='DC voltage rating on node 1', unit='kV', non_zero=True, tex_name='V_{dcn1}', ) self.Vdcn2 = NumParam( default=100, info='DC voltage rating on node 2', unit='kV', non_zero=True, tex_name='V_{dcn2}', ) self.Idcn = NumParam( default=1, info='DC current rating', unit='kA', non_zero=True, tex_name='I_{dcn}', ) Model.__init__(self, system, config) self.v1 = ExtAlgeb( model='Node', src='v', indexer=self.node1, info='DC voltage on node 1', ) self.v2 = ExtAlgeb( model='Node', src='v', indexer=self.node2, info='DC voltage on node 2', )
def __init__(self, system, config): ModelData.__init__(self) Model.__init__(self, system, config) self.flags.tds = True self.group = 'FreqMeasurement' # Parameters self.bus = IdxParam(info="bus idx", mandatory=True) self.Tf = NumParam(default=0.02, info="input digital filter time const", unit="sec", tex_name='T_f') self.Tw = NumParam(default=0.02, info="washout time const", unit="sec", tex_name='T_w') self.fn = NumParam(default=60.0, info="nominal frequency", unit='Hz', tex_name='f_n') # Variables self.iwn = ConstService(v_str='u / (2 * pi * fn)', tex_name=r'1/\omega_n') self.a0 = ExtService(src='a', model='Bus', indexer=self.bus, tex_name=r'\theta_0', info='initial phase angle', ) self.a = ExtAlgeb(model='Bus', src='a', indexer=self.bus, tex_name=r'\theta', ) self.v = ExtAlgeb(model='Bus', src='v', indexer=self.bus, tex_name=r'V', ) self.L = Lag(u='(a-a0)', T=self.Tf, K=1, info='digital filter', ) self.WO = Washout(u=self.L_y, K=self.iwn, T=self.Tw, info='angle washout', ) self.f = Algeb(info='frequency output', unit='p.u. (Hz)', tex_name='f', v_str='1', e_str='1 + WO_y - f', )
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, 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): ACEData.__init__(self) Model.__init__(self, system, config) self.flags.tds = True self.group = 'Calculation' 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', default_model='BusFreq') self.imva = ConstService(v_str='1/sys_mva', info='reciprocal of system mva', tex_name='1/S_{b, sys}') self.f = ExtAlgeb(model='FreqMeasurement', src='f', indexer=self.busfreq, export=False, info='Bus frequency', unit='p.u. (Hz)') self.ace = Algeb( info='area control error', unit='p.u. (MW)', tex_name='ace', e_str='10 * (bias * imva) * sys_f * (f - 1) - ace', )
def get_times(self): """ Gather simulation stop-at times for mode = 1. """ Model.get_times(self) # collect all time stamps out = list() for ii in range(self.n): if self.SW.s1[ii] != 1: continue idx = self.idx.v[ii] df = self._data[idx] tkey = self.tkey.v[ii] out.append(df[tkey].to_numpy()) return out
def __init__(self, system, config): Model.__init__(self, system, config) self.flags.tds = True self.group = 'Experimental' self.a = ExtAlgeb( model='Bus', src='a', indexer=self.bus, tex_name=r'\theta', info='Bus voltage angle', e_str='-p0', ename='P', tex_ename='P', ) self.v = ExtAlgeb( model='Bus', src='v', indexer=self.bus, tex_name=r'V', info='Bus voltage magnitude', e_str='-q0', ename='P', tex_ename='P', ) self.p0 = ExtService( model='StaticGen', src='p', indexer=self.gen, tex_name='P_0', ) self.q0 = ExtService( model='StaticGen', src='q', indexer=self.gen, tex_name='Q_0', )
def list2array(self): """ Set internal storage for timeseries data. Open file and read data into internal storage. """ # TODO: timeseries file must exist for setup to pass. Consider moving # the file reading to a later stage so that adding sheets to xlsx file can work # without the file existing. Model.list2array(self) # read and store data for ii in range(self.n): idx = self.idx.v[ii] path = self.path.v[ii] sheet = self.sheet.v[ii] if not os.path.isabs(path): path = os.path.join(self.system.files.case_path, path) if not os.path.exists(path): raise FileNotFoundError('<%s idx=%s>: File not found: "%s"', self.class_name, idx, path) # --- read supported formats --- if path.endswith("xlsx") or path.endswith("xls"): df = self._read_excel(path, sheet, idx) elif path.endswith("csv"): df = pd.read_csv(path) for field in self.fields.v[ii]: if field not in df.columns: raise ValueError( 'Field {} not found in timeseries data'.format(field)) self._data[idx] = df logger.info('Read timeseries data from "%s"', path)