def __init__(self, system=None, config=None): SlackData.__init__(self) PVModel.__init__(self, system, config) self.config.add(OrderedDict((('av2pv', 0), ))) self.config.add_extra( "_help", av2pv="convert Slack to PV in PFlow at P limits", ) self.config.add_extra( "_alt", av2pv=(0, 1), ) self.config.add_extra( "_tex", av2pv="z_{av2pv}", ) self.a.v_setter = True self.a.v_str = 'a0' self.plim = SortedLimiter(u=self.p, lower=self.pmin, upper=self.pmax, enable=self.config.av2pv) self.p.e_str = "u*(plim_zi * (a0-a) + "\ "plim_zl * (pmin-p) + "\ "plim_zu * (pmax-p))"
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.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}", ) 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) + "\ "qlim_zl * (qmin-q) + "\ "qlim_zu * (qmax-q))"
def __init__(self, system=None, config=None): SlackData.__init__(self) PVModel.__init__(self, system, config) self.config.add(OrderedDict((('av2pv', 0.), ))) self.a.v_setter = True self.a.v_str = 'a0' self.plim = SortedLimiter(u=self.p, lower=self.pmin, upper=self.pmax, enable=self.config.av2pv) self.p.e_str = "u * (plim_zi * (a0 - a) + \
def test_sorted_limiter(self): """ Tests for `SortedLimiter` class Returns ------- """ self.cmp = Limiter(self.u, self.lower, self.upper) self.cmp.list2array(len(self.u.v)) self.cmp.check_var() self.rcmp = SortedLimiter(self.u, self.lower, self.upper, n_select=1) self.rcmp.list2array(len(self.u.v)) self.rcmp.check_var() self.assertSequenceEqual(self.rcmp.zl.tolist(), [0., 0., 1., 0., 0., 0., 0., 0.]) self.assertSequenceEqual(self.rcmp.zi.tolist(), [1., 1., 0., 1., 1., 1., 1., 0.]) self.assertSequenceEqual(self.rcmp.zu.tolist(), [0., 0., 0., 0., 0., 0., 0., 1.]) # test when no `n_select` is specified self.rcmp_noselect = SortedLimiter(self.u, self.lower, self.upper) self.rcmp_noselect.list2array(len(self.u.v)) self.rcmp_noselect.check_var() self.assertSequenceEqual(self.rcmp_noselect.zl.tolist(), self.cmp.zl.tolist()) self.assertSequenceEqual(self.rcmp_noselect.zi.tolist(), self.cmp.zi.tolist()) self.assertSequenceEqual(self.rcmp_noselect.zu.tolist(), self.cmp.zu.tolist()) # test when no `n_select` is over range self.rcmp_noselect = SortedLimiter(self.u, self.lower, self.upper, n_select=999) self.rcmp_noselect.list2array(len(self.u.v)) self.rcmp_noselect.check_var() self.assertSequenceEqual(self.rcmp_noselect.zl.tolist(), self.cmp.zl.tolist()) self.assertSequenceEqual(self.rcmp_noselect.zi.tolist(), self.cmp.zi.tolist()) self.assertSequenceEqual(self.rcmp_noselect.zu.tolist(), self.cmp.zu.tolist())
class TestDiscrete(unittest.TestCase): 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 test_limiter(self): """ Tests for `Limiter` class Returns ------- """ self.cmp = Limiter(self.u, self.lower, self.upper) self.cmp.list2array(len(self.u.v)) self.cmp.check_var() self.assertSequenceEqual(self.cmp.zl.tolist(), [1., 1., 1., 1., 0., 0., 0., 0.]) self.assertSequenceEqual(self.cmp.zi.tolist(), [0., 0., 0., 0., 1., 0., 0., 0.]) self.assertSequenceEqual(self.cmp.zu.tolist(), [0., 0., 0., 0., 0., 1., 1., 1.]) def test_sorted_limiter(self): """ Tests for `SortedLimiter` class Returns ------- """ self.cmp = Limiter(self.u, self.lower, self.upper) self.cmp.list2array(len(self.u.v)) self.cmp.check_var() self.rcmp = SortedLimiter(self.u, self.lower, self.upper, n_select=1) self.rcmp.list2array(len(self.u.v)) self.rcmp.check_var() self.assertSequenceEqual(self.rcmp.zl.tolist(), [0., 0., 1., 0., 0., 0., 0., 0.]) self.assertSequenceEqual(self.rcmp.zi.tolist(), [1., 1., 0., 1., 1., 1., 1., 0.]) self.assertSequenceEqual(self.rcmp.zu.tolist(), [0., 0., 0., 0., 0., 0., 0., 1.]) # test when no `n_select` is specified self.rcmp_noselect = SortedLimiter(self.u, self.lower, self.upper) self.rcmp_noselect.list2array(len(self.u.v)) self.rcmp_noselect.check_var() self.assertSequenceEqual(self.rcmp_noselect.zl.tolist(), self.cmp.zl.tolist()) self.assertSequenceEqual(self.rcmp_noselect.zi.tolist(), self.cmp.zi.tolist()) self.assertSequenceEqual(self.rcmp_noselect.zu.tolist(), self.cmp.zu.tolist()) # test when no `n_select` is over range self.rcmp_noselect = SortedLimiter(self.u, self.lower, self.upper, n_select=999) self.rcmp_noselect.list2array(len(self.u.v)) self.rcmp_noselect.check_var() self.assertSequenceEqual(self.rcmp_noselect.zl.tolist(), self.cmp.zl.tolist()) self.assertSequenceEqual(self.rcmp_noselect.zi.tolist(), self.cmp.zi.tolist()) self.assertSequenceEqual(self.rcmp_noselect.zu.tolist(), self.cmp.zu.tolist()) def test_switcher(self): p = NumParam() p.v = np.array([0, 1, 2, 2, 1, 3, 1]) switcher = Switcher(u=p, options=[0, 1, 2, 3, 4]) switcher.list2array(len(p.v)) switcher.check_var() self.assertSequenceEqual(switcher.s0.tolist(), [1, 0, 0, 0, 0, 0, 0]) self.assertSequenceEqual(switcher.s1.tolist(), [0, 1, 0, 0, 1, 0, 1]) self.assertSequenceEqual(switcher.s2.tolist(), [0, 0, 1, 1, 0, 0, 0]) self.assertSequenceEqual(switcher.s3.tolist(), [0, 0, 0, 0, 0, 1, 0]) self.assertSequenceEqual(switcher.s4.tolist(), [0, 0, 0, 0, 0, 0, 0])
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))"