Ejemplo n.º 1
0
    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')
Ejemplo n.º 2
0
    def __init__(self):
        super().__init__()
        self.common_params.extend(('syn',))
        self.common_vars.extend(('vout', 'vi',))

        self.VoltComp = BackRef()
        self.PSS = BackRef()
Ejemplo n.º 3
0
    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()
Ejemplo n.º 4
0
    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()
Ejemplo n.º 5
0
    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()
Ejemplo n.º 6
0
    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()
Ejemplo n.º 7
0
    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')
Ejemplo n.º 8
0
    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,
        )
Ejemplo n.º 9
0
    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))"
Ejemplo n.º 10
0
Archivo: pv.py Proyecto: whoiszyc/andes
    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))"