Example #1
0
def get_power_flow_interface_expr_ptdf(model,
                                       interface_name,
                                       PTDF,
                                       rel_ptdf_tol=None,
                                       abs_ptdf_tol=None):
    """
    Create a pyomo power flow expression from PTDF matrix for an interface
    """
    if rel_ptdf_tol is None:
        rel_ptdf_tol = 0.
    if abs_ptdf_tol is None:
        abs_ptdf_tol = 0.

    const = PTDF.get_interface_const(interface_name)
    max_coef = PTDF.get_interface_ptdf_abs_max(interface_name)

    ptdf_tol = max(abs_ptdf_tol, rel_ptdf_tol * max_coef)

    m_p_nw = model.p_nw

    ## if model.p_nw is Var, we can use LinearExpression
    ## to build these dense constraints much faster
    if isinstance(m_p_nw, pe.Var):
        coef_list = list()
        var_list = list()
        for bus_name, coef in PTDF.get_interface_ptdf_iterator(interface_name):
            if abs(coef) >= ptdf_tol:
                coef_list.append(coef)
                var_list.append(m_p_nw[bus_name])
        if interface_name in model.pfi_slack_neg:
            coef_list.append(1)
            var_list.append(model.pfi_slack_neg[interface_name])
        if interface_name in model.pfi_slack_pos:
            coef_list.append(-1)
            var_list.append(model.pfi_slack_pos[interface_name])

        lin_expr_list = [const] + coef_list + var_list
        expr = LinearExpression(lin_expr_list)
    else:
        expr = quicksum(
            (coef * m_p_nw[bus_name]
             for bus_name, coef in PTDF.get_interface_ptdf_iterator(
                 interface_name) if abs(coef) >= ptdf_tol),
            start=const,
            linear=True)
        if interface_name in model.pfi_slack_neg:
            expr += model.pfi_slack_neg[interface_name]
        if interface_name in model.pfi_slack_pos:
            expr -= model.pfi_slack_pos[interface_name]

    return expr
Example #2
0
def get_branch_loss_expr_ptdf_approx(model,
                                     branch_name,
                                     PTDF,
                                     rel_ptdf_tol=None,
                                     abs_ptdf_tol=None):
    """
    Create a pyomo power flow loss expression from PTDF matrix
    """
    if rel_ptdf_tol is None:
        rel_ptdf_tol = 0.
    if abs_ptdf_tol is None:
        abs_ptdf_tol = 0.

    const = PTDF.get_branch_losses_phase_shift(branch_name)
    const += PTDF.get_branch_ldf_c(branch_name)
    const += PTDF.get_branch_phi_losses_adj(branch_name)

    max_coef = PTDF.get_branch_ldf_abs_max(branch_name)

    ptdf_tol = max(abs_ptdf_tol, rel_ptdf_tol * max_coef)
    ## NOTE: It would be easy to hold on to the 'ptdf' dictionary here,
    ##       if we wanted to
    m_p_nw = model.p_nw
    ## if model.p_nw is Var, we can use LinearExpression
    ## to build these dense constraints much faster
    if isinstance(m_p_nw, pe.Var):
        coef_list = list()
        var_list = list()
        for bus_name, coef in PTDF.get_branch_ldf_iterator(branch_name):
            if abs(coef) >= ptdf_tol:
                coef_list.append(coef)
                var_list.append(m_p_nw[bus_name])

        lin_expr_list = [const] + coef_list + var_list
        expr = LinearExpression(lin_expr_list)
    else:
        expr = quicksum(
            (coef * m_p_nw[bus_name]
             for bus_name, coef in PTDF.get_branch_ldf_iterator(branch_name)
             if abs(coef) >= ptdf_tol),
            start=const,
            linear=True)

    return expr
Example #3
0
    def create_optimization_model(self, config):

        self.logger.info('Creating optimization model.')

        # Consider using context managers

        # limit_sell = False

        # GET COMPONENTS FROM SYSTEM

        if self.system.has_battery:
            battery = self.system.get_battery_object()

        if self.system.has_external_grid:
            supply = self.system.get_external_grid_object()

        # STARTING MODEL

        m = pk.block()

        # Track the default attributes of the model to be aware of which the user adds.
        default_attributes = set(m.__dict__.keys())
        default_attributes.add('default_attributes')

        # SETS

        m.periods = range(config['periods'])
        m.E_set = []

        # VARIABLES

        m.E = pk.variable_dict()

        if self.system.has_stochastic_generators and not self.system.has_external_grid:
            m.E_set.append('stochastic')

            m.E['stochastic'] = pk.variable_list()
            for t in m.periods:
                m.E['stochastic'].append(
                    pk.variable(domain_type=pk.RealSet,
                                lb=0,
                                ub=self.system.stochastic_electrical_gen[t]))

        if self.system.has_external_grid:
            m.E_set.append('buy')
            m.E_set.append('sell')

            m.E['buy'] = pk.variable_list()
            for _ in m.periods:
                m.E['buy'].append(pk.variable(domain=pk.NonNegativeReals))

            m.E['sell'] = pk.variable_list()
            for _ in m.periods:
                m.E['sell'].append(pk.variable(domain=pk.NonNegativeReals))

            m.y_grid = pk.variable_list()
            for _ in m.periods:
                m.y_grid.append(
                    pk.variable(domain_type=pk.IntegerSet, lb=0, ub=1))

        if self.system.has_battery:
            m.E_set.append('batt_chrg')
            m.E_set.append('batt_dis')

            m.E['batt_chrg'] = pk.variable_list()
            for _ in m.periods:
                # The upper bound are impose in the constraints below
                m.E['batt_chrg'].append(
                    pk.variable(domain_type=pk.RealSet, lb=0))
            m.E['batt_dis'] = pk.variable_list()
            for _ in m.periods:
                m.E['batt_dis'].append(
                    pk.variable(domain_type=pk.RealSet, lb=0))

            m.y_bat = pk.variable_list()
            for _ in m.periods:
                m.y_bat.append(
                    pk.variable(domain_type=pk.IntegerSet, lb=0, ub=1))

            m.soc = pk.variable_list()
            for _ in m.periods:
                m.soc.append(
                    pk.variable(domain_type=pk.RealSet,
                                lb=battery.soc_lb,
                                ub=battery.soc_ub))
            # Extra soc variable for the last value of soc that should be >= soc_l
            m.soc.append(
                pk.variable(domain_type=pk.RealSet,
                            lb=battery.soc_l,
                            ub=battery.soc_ub))

        # PARAMETERS

        if self.system.has_external_grid:
            m.prices = {
                'buy': supply.electricity_purchase_prices.copy(),
                'sell': supply.electricity_selling_prices.copy(),
            }

        # OBJECTIVE FUNCTION

        obj_exp = 0
        obj_sense = pk.minimize

        if self.system.has_external_grid:
            obj_exp = quicksum((m.E['buy'][t] * m.prices['buy'][t] for t in m.periods), linear=True) \
                   - quicksum((m.E['sell'][t] * m.prices['sell'][t] for t in m.periods), linear=True)

        m.obj = pk.objective(obj_exp, sense=obj_sense)

        # CONSTRAINTS

        # Grid constraints

        # if limit_sell:
        #     m.c_limit_sell = pk.constraint(
        #             lb=0, body=system['selling_ratio']
        #             * sum(m.E['buy'][t] + system['E_pv'][t] for t in m.periods)
        #             - sum(m.E['sell'][t] for t in m.periods))

        grid_m = 1e5
        m.cl_y_buy = pk.constraint_list()
        for t in m.periods:
            m.cl_y_buy.append(
                pk.constraint(body=m.y_grid[t] * grid_m - m.E['buy'][t], lb=0))

        m.cl_y_sell = pk.constraint_list()
        for t in m.periods:
            m.cl_y_sell.append(
                pk.constraint(body=(1 - m.y_grid[t]) * grid_m - m.E['sell'][t],
                              lb=0))

        # Balance constraints

        energy_balance_exp = [0 for _ in m.periods]

        if self.system.has_fix_loads:
            for t in m.periods:
                energy_balance_exp[t] = -1 * self.system.fix_electrical_load[t]

        if self.system.has_external_grid:
            for t in m.periods:
                energy_balance_exp[
                    t] = energy_balance_exp[t] + m.E['buy'][t] - m.E['sell'][t]

        if self.system.has_battery:
            for t in m.periods:
                energy_balance_exp[t] = energy_balance_exp[t] + m.E[
                    'batt_dis'][t] - m.E['batt_chrg'][t]

        if self.system.has_stochastic_generators and not self.system.has_external_grid:
            for t in m.periods:
                energy_balance_exp[
                    t] = energy_balance_exp[t] + m.E['stochastic'][t]
        else:
            for t in m.periods:
                energy_balance_exp[t] = energy_balance_exp[
                    t] + self.system.stochastic_electrical_gen[t]

        m.cl_balance = pk.constraint_list()
        for t in m.periods:
            m.cl_balance.append(
                pk.constraint(body=energy_balance_exp[t], rhs=0))

        # Battery constraints and restrictions

        if self.system.has_battery:
            m.soc[0].fix(battery.soc_0)

            m.cl_soc = pk.constraint_list()
            for t in m.periods:
                m.cl_soc.append(
                    pk.constraint(
                        body=battery.batt_C * (m.soc[t + 1] - m.soc[t]) +
                        1 / battery.batt_dis_per * m.E['batt_dis'][t] -
                        battery.batt_chrg_per * m.E['batt_chrg'][t],
                        rhs=0))

            m.cl_y_char = pk.constraint_list()
            for t in m.periods:
                m.cl_y_char.append(
                    pk.constraint(body=m.y_bat[t] * battery.batt_chrg_speed -
                                  m.E['batt_chrg'][t],
                                  lb=0))

            m.cl_y_dis = pk.constraint_list()
            for t in m.periods:
                m.cl_y_char.append(
                    pk.constraint(
                        body=(1 - m.y_bat[t]) * battery.batt_dis_speed -
                        m.E['batt_dis'][t],
                        lb=0))

        # FINISHING

        # Determine the user defined attributes (written in this source code) by subtracting the defaults one.
        all_attributes = set(m.__dict__.keys())
        m.user_defined_attributes = list(all_attributes - default_attributes)

        self.optimization_model = m

        return m