Exemple #1
0
    def compute_branch_results(self, V):
        """
        Compute the branch magnitudes from the voltages
        :param V: Voltage vector solution in p.u.
        :return: CalculationResults instance with all the grid magnitudes
        """

        # declare circuit results
        data = PowerFlowResults(self.nbus, self.nbr)

        # copy the voltage
        data.V = V

        # power at the slack nodes
        data.Sbus = self.Sbus.copy()
        data.Sbus[self.ref] = V[self.ref] * np.conj(
            self.Ybus[self.ref, :].dot(V))

        # Reactive power at the pv nodes: keep the original P injection and set the calculated reactive power
        Q = (V[self.pv] * np.conj(self.Ybus[self.pv, :].dot(V))).imag

        data.Sbus[self.pv] = self.Sbus[self.pv].real + 1j * Q

        # Branches current, loading, etc
        data.If = self.Yf * V
        data.It = self.Yt * V
        data.Sf = self.C_branch_bus_f * V * np.conj(data.If)
        data.St = self.C_branch_bus_t * V * np.conj(data.It)

        # Branch losses in MVA
        data.losses = (data.Sf + data.St)

        # Branch current in p.u.
        data.Ibranch = np.maximum(data.If, data.It)

        # Branch power in MVA
        data.Sbranch = np.maximum(data.Sf, data.St)

        # Branch loading in p.u.
        data.loading = data.Sbranch / (self.branch_rates + 1e-9)

        return data
Exemple #2
0
def outer_loop_power_flow(circuit: SnapshotData, options: PowerFlowOptions,
                          voltage_solution, Sbus, Ibus, branch_rates, t=0,
                          logger=bs.Logger()) -> "PowerFlowResults":
    """
    Run a power flow simulation for a single circuit using the selected outer loop
    controls. This method shouldn't be called directly.
    :param circuit: CalculationInputs instance
    :param options:
    :param voltage_solution: vector of initial voltages
    :param Sbus: vector of power injections
    :param Ibus: vector of current injections
    :param branch_rates:
    :param t: time step
    :param logger:
    :return: PowerFlowResults instance
    """

    # get the original types and compile this class' own lists of node types for thread independence
    bus_types = circuit.bus_types.copy()

    # vd = circuit.vd.copy()
    # pq = circuit.pq.copy()
    # pv = circuit.pv.copy()
    # pqpv = circuit.pqpv.copy()

    report = ConvergenceReport()
    solution = NumericPowerFlowResults(V=voltage_solution,
                                       converged=False,
                                       norm_f=1e200,
                                       Scalc=Sbus,
                                       ma=circuit.branch_data.m[:, 0],
                                       theta=circuit.branch_data.theta[:, 0],
                                       Beq=circuit.branch_data.Beq[:, 0],
                                       iterations=0,
                                       elapsed=0)

    # this the "outer-loop"
    if len(circuit.vd) == 0:
        voltage_solution = np.zeros(len(Sbus), dtype=complex)
        normF = 0
        Scalc = Sbus.copy()
        any_q_control_issue = False
        converged = True
        logger.add_error('Not solving power flow because there is no slack bus')
    else:

        # run the power flow method that shall be run
        solution = solve(circuit=circuit,
                         options=options,
                         report=report,  # is modified here
                         V0=voltage_solution,
                         Sbus=Sbus,
                         Ibus=Ibus,
                         pq=circuit.pq,
                         pv=circuit.pv,
                         ref=circuit.vd,
                         pqpv=circuit.pqpv,
                         logger=logger)

        if options.distributed_slack:
            # Distribute the slack power
            slack_power = Sbus[circuit.vd].real.sum()
            total_installed_power = circuit.bus_installed_power.sum()

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

                # repeat power flow with the redistributed power
                solution = solve(circuit=circuit,
                                 options=options,
                                 report=report,  # is modified here
                                 V0=solution.V,
                                 Sbus=Sbus + delta,
                                 Ibus=Ibus,
                                 pq=circuit.pq,
                                 pv=circuit.pv,
                                 ref=circuit.vd,
                                 pqpv=circuit.pqpv,
                                 logger=logger)

    # Compute the branches power and the slack buses power
    Sfb, Stb, If, It, Vbranch, loading, losses, \
     flow_direction, Sbus = power_flow_post_process(calculation_inputs=circuit,
                                                    Sbus=solution.Scalc,
                                                    V=solution.V,
                                                    branch_rates=branch_rates)

    # voltage, Sf, loading, losses, error, converged, Qpv
    results = PowerFlowResults(n=circuit.nbus,
                               m=circuit.nbr,
                               n_tr=circuit.ntr,
                               n_hvdc=circuit.nhvdc,
                               bus_names=circuit.bus_names,
                               branch_names=circuit.branch_names,
                               transformer_names=circuit.tr_names,
                               hvdc_names=circuit.hvdc_names,
                               bus_types=bus_types)

    results.Sbus = solution.Scalc * circuit.Sbase  # MVA
    results.voltage = solution.V
    results.Sf = Sfb  # in MVA already
    results.St = Stb  # in MVA already
    results.If = If  # in p.u.
    results.It = It  # in p.u.
    results.ma = solution.ma
    results.theta = solution.theta
    results.Beq = solution.Beq
    results.Vbranch = Vbranch
    results.loading = loading
    results.losses = losses
    results.flow_direction = flow_direction
    results.transformer_tap_module = solution.ma[circuit.transformer_idx]
    results.convergence_reports.append(report)
    results.Qpv = Sbus.imag[circuit.pv]

    # HVDC results are gathered in the multi island power flow function due to their nature

    return results