示例#1
0
    def vd(self):

        if self.vd_ is None:
            self.vd_, self.pq_, self.pv_, self.pqpv_ = compile_types(
                Sbus=self.Sbus[:, 0], types=self.bus_data.bus_types)

        return self.vd_
示例#2
0
    def consolidate(self):
        """
        Computes the parameters given the filled-in information
        :return:
        """
        self.compute_injections()

        self.vd, self.pq, self.pv, self.pqpv = compile_types(Sbus=self.Sbus, types=self.bus_types)

        self.compute_reactive_power_limits()
    def consolidate(self):
        """
        Computes the parameters given the filled-in information
        :return:
        """
        self.compute_injections()

        self.vd, self.pq, self.pv, self.pqpv = compile_types(
            Sbus=self.Sbus[:, 0], types=self.bus_types)

        self.compute_admittance_matrices()
示例#4
0
    def compute_dynamic_types(self):
        """
        Compute bus types profiles
        :return:
        """
        self.vd_prof_ = list()
        self.pq_prof_ = list()
        self.pv_prof_ = list()
        self.pqpv_prof_ = list()

        for t in range(self.ntime):
            vd, pq, pv, pqpv = compile_types(
                Sbus=self.Sbus[:, t], types=self.bus_data.bus_types_prof[:, t])
            self.vd_prof_.append(vd)
            self.pq_prof_.append(pq)
            self.pv_prof_.append(pv)
            self.pqpv_prof_.append(pqpv)
示例#5
0
def continuation_nr(Ybus,
                    Cf,
                    Ct,
                    Yf,
                    Yt,
                    branch_rates,
                    Sbase,
                    Ibus_base,
                    Ibus_target,
                    Sbus_base,
                    Sbus_target,
                    V,
                    distributed_slack,
                    bus_installed_power,
                    vd,
                    pv,
                    pq,
                    step,
                    approximation_order: CpfParametrization,
                    adapt_step,
                    step_min,
                    step_max,
                    error_tol=1e-3,
                    tol=1e-6,
                    max_it=20,
                    stop_at=CpfStopAt.Nose,
                    control_q=ReactivePowerControlMode.NoControl,
                    qmax_bus=None,
                    qmin_bus=None,
                    original_bus_types=None,
                    base_overload_number=0,
                    verbose=False,
                    call_back_fx=None,
                    logger=Logger()) -> CpfNumericResults:
    """
    Runs a full AC continuation power flow using a normalized tangent
    predictor and selected approximation_order scheme.
    :param Ybus: Admittance matrix
    :param Cf: Connectivity matrix of the branches and the "from" nodes
    :param Ct: Connectivity matrix of the branches and the "to" nodes
    :param Yf: Admittance matrix of the "from" nodes
    :param Yt: Admittance matrix of the "to" nodes
    :param branch_rates: array of branch rates to check the overload condition
    :param Ibus_base:
    :param Ibus_target:
    :param Sbus_base: Power array of the base solvable case
    :param Sbus_target: Power array of the case to be solved
    :param V: Voltage array of the base solved case
    :param distributed_slack: Distribute the slack?
    :param bus_installed_power: array of installed power per bus
    :param vd: Array of slack bus indices
    :param pv: Array of pv bus indices
    :param pq: Array of pq bus indices
    :param step: Adaptation step
    :param approximation_order: order of the approximation {Natural, Arc, Pseudo arc}
    :param adapt_step: use adaptive step size?
    :param step_min: minimum step size
    :param step_max: maximum step size
    :param error_tol: Error tolerance
    :param tol: Solutions tolerance
    :param max_it: Maximum iterations
    :param stop_at:  Value of Lambda to stop at. It can be a number or {'NOSE', 'FULL'}
    :param control_q: Type of reactive power control
    :param qmax_bus: Array of maximum reactive power per node
    :param qmin_bus: Array of minimum reactive power per node
    :param original_bus_types: array of bus types
    :param base_overload_number: number of overloads in the base situation (used when stop_at=CpfStopAt.ExtraOverloads)
    :param verbose: Display additional intermediate information?
    :param call_back_fx: Function to call on every iteration passing the lambda parameter
    :param logger: Logger instance
    :return: CpfNumericResults instance


    Ported from MATPOWER
        Copyright (c) 1996-2015 by Power System Engineering Research Center (PSERC)
        by Ray Zimmerman, PSERC Cornell,
        Shrirang Abhyankar, Argonne National Laboratory, and Alexander Flueck, IIT

        $Id: runcpf.m 2644 2015-03-11 19:34:22Z ray $

        MATPOWER is covered by the 3-clause BSD License (see LICENSE file for details).
        See http://www.pserc.cornell.edu/matpower/ for more info.
    """

    ########################################
    # INITIALIZATION
    ########################################

    # scheduled transfer
    Sxfr = Sbus_target - Sbus_base
    nb = len(Sbus_base)
    lam = 0
    lam_prev = lam  # lam at previous step
    V_prev = V  # V at previous step
    continuation = True
    cont_steps = 0
    pvpq = np.r_[pv, pq]
    bus_types = original_bus_types.copy()

    z = np.zeros(2 * nb + 1)
    z[2 * nb] = 1.0

    # generate lookup pvpq -> index pvpq (used in createJ)
    pvpq_lookup = np.zeros(np.max(Ybus.indices) + 1, dtype=int)
    pvpq_lookup[pvpq] = np.arange(len(pvpq))

    # compute total bus installed power
    total_installed_power = bus_installed_power.sum()

    # result arrays
    results = CpfNumericResults()

    # Simulation
    while continuation:
        cont_steps += 1

        # prediction for next step -------------------------------------------------------------------------------------
        V0, lam0, z = predictor(V=V,
                                Ibus=Ibus_base,
                                lam=lam,
                                Ybus=Ybus,
                                Sxfr=Sxfr,
                                pv=pv,
                                pq=pq,
                                step=step,
                                z=z,
                                Vprv=V_prev,
                                lamprv=lam_prev,
                                parametrization=approximation_order,
                                pvpq_lookup=pvpq_lookup)

        # save previous voltage, lambda before updating
        V_prev = V.copy()
        lam_prev = lam

        # correction ---------------------------------------------------------------------------------------------------
        V, success, i, lam, normF, Scalc = corrector(
            Ybus=Ybus,
            Ibus=Ibus_base,
            Sbus=Sbus_base,
            V0=V0,
            pv=pv,
            pq=pq,
            lam0=lam0,
            Sxfr=Sxfr,
            Vprv=V_prev,
            lamprv=lam_prev,
            z=z,
            step=step,
            parametrization=approximation_order,
            tol=tol,
            max_it=max_it,
            pvpq_lookup=pvpq_lookup,
            verbose=verbose)

        if distributed_slack:
            # Distribute the slack power
            slack_power = Scalc[vd].real.sum()

            if total_installed_power > 0.0:
                delta = slack_power * bus_installed_power / total_installed_power

                # rerun with the slack distributed and replace the results
                # also, initialize with the last voltage
                V, success, i, lam, normF, Scalc = corrector(
                    Ybus=Ybus,
                    Ibus=Ibus_base,
                    Sbus=Sbus_base + delta,
                    V0=V,
                    pv=pv,
                    pq=pq,
                    lam0=lam0,
                    Sxfr=Sxfr,
                    Vprv=V_prev,
                    lamprv=lam_prev,
                    z=z,
                    step=step,
                    parametrization=approximation_order,
                    tol=tol,
                    max_it=max_it,
                    pvpq_lookup=pvpq_lookup,
                    verbose=verbose)

        if success:

            # branch values --------------------------------------------------------------------------------------------
            # Branches current, loading, etc
            Vf = Cf * V
            Vt = Ct * V
            If = Yf * V  # in p.u.
            It = Yt * V  # in p.u.
            Sf = Vf * np.conj(If) * Sbase  # in MVA
            St = Vt * np.conj(It) * Sbase  # in MVA

            # Branch losses in MVA
            losses = Sf + St

            # Branch loading in p.u.
            loading = Sf.real / (branch_rates + 1e-9)

            # store series values --------------------------------------------------------------------------------------

            results.add(V, Scalc, Sf, St, lam, losses, loading, normF, success)

            if verbose:
                print('Step: ', cont_steps, ' Lambda prev: ', lam_prev,
                      ' Lambda: ', lam)
                print(V)

            # Check controls
            if control_q == ReactivePowerControlMode.Direct:
                Vm = np.abs(V)
                V, \
                Qnew, \
                types_new, \
                any_q_control_issue = control_q_direct(V=V,
                                                       Vm=Vm,
                                                       Vset=Vm,
                                                       Q=Scalc.imag,
                                                       Qmax=qmax_bus,
                                                       Qmin=qmin_bus,
                                                       types=bus_types,
                                                       original_types=original_bus_types,
                                                       verbose=verbose)
            else:
                # did not check Q limits
                any_q_control_issue = False
                types_new = bus_types
                Qnew = Scalc.imag

            # Check the actions of the Q-control
            if any_q_control_issue:
                bus_types = types_new
                Sbus = Scalc.real + 1j * Qnew

                Sxfr = Sbus_target - Sbus  # TODO: really?

                vd, pq, pv, pqpv = compile_types(Sbus, types_new, logger)
            else:
                if verbose:
                    print('Q controls Ok')

            if stop_at == CpfStopAt.Full:

                if abs(lam) < 1e-8:
                    # traced the full continuation curve
                    if verbose:
                        print('\nTraced full continuation curve in ',
                              cont_steps, ' continuation steps\n')
                    continuation = False

                elif (lam < lam_prev) and (lam - step < 0):
                    # next step will overshoot

                    # modify step-size
                    step = lam

                    # change to natural parametrization
                    approximation_order = CpfParametrization.Natural

                    # disable step-adaptivity
                    adapt_step = 0

            elif stop_at == CpfStopAt.Nose:

                if lam < lam_prev:
                    # reached the nose point
                    if verbose:
                        print('\nReached steady state loading limit in ',
                              cont_steps, ' continuation steps\n')
                    continuation = False

            elif stop_at == CpfStopAt.ExtraOverloads:
                # look for overloads and determine if there are more overloads than in the base situation
                idx = np.where(np.abs(loading) > 1)[0]
                if len(idx) > base_overload_number:
                    continuation = False

            else:
                raise Exception('Stop point ' + stop_at.value +
                                ' not recognised.')

            if adapt_step and continuation:

                # Adapt step size
                fx = np.r_[np.angle(V[pq]),
                           np.abs(V[pvpq]), lam] - np.r_[np.angle(V0[pq]),
                                                         np.abs(V0[pvpq]),
                                                         lam0]
                cpf_error = np.linalg.norm(fx, np.Inf)

                if cpf_error == 0:
                    cpf_error = 1e-20

                if cpf_error < error_tol:
                    # Increase step size
                    step = step * error_tol / cpf_error
                    if step > step_max:
                        step = step_max

                else:
                    # Decrease step size
                    step = step * error_tol / cpf_error
                    if step < step_min:
                        step = step_min

            # call callback function
            if call_back_fx is not None:
                call_back_fx(lam)

        else:
            continuation = False
            if verbose:
                print('step ', cont_steps, ' : lambda = ', lam,
                      ', corrector did not converge in ', i, ' iterations\n')

    return results