Ejemplo n.º 1
0
def _include_feasibility_slack(model, bus_attrs, gen_attrs, bus_p_loads,
                               p_marginal_slack_penalty):
    import egret.model_library.decl as decl
    slack_init = {k: 0 for k in bus_attrs['names']}

    slack_bounds = {
        k: (0, sum(bus_p_loads.values()))
        for k in bus_attrs['names']
    }
    decl.declare_var('p_over_generation',
                     model=model,
                     index_set=bus_attrs['names'],
                     initialize=slack_init,
                     bounds=slack_bounds)
    decl.declare_var('p_load_shed',
                     model=model,
                     index_set=bus_attrs['names'],
                     initialize=slack_init,
                     bounds=slack_bounds)
    p_rhs_kwargs = {
        'include_feasibility_slack_pos': 'p_over_generation',
        'include_feasibility_slack_neg': 'p_load_shed'
    }

    penalty_expr = sum(
        p_marginal_slack_penalty *
        (model.p_over_generation[bus_name] + model.p_load_shed[bus_name])
        for bus_name in bus_attrs['names'])
    return p_rhs_kwargs, penalty_expr
Ejemplo n.º 2
0
def _include_feasibility_slack(model,
                               bus_attrs,
                               gen_attrs,
                               bus_p_loads,
                               penalty=1000):
    import egret.model_library.decl as decl
    slack_init = {k: 0 for k in bus_attrs['names']}
    slack_bounds = {
        k: (0, sum(bus_p_loads.values()))
        for k in bus_attrs['names']
    }
    decl.declare_var('p_slack_pos',
                     model=model,
                     index_set=bus_attrs['names'],
                     initialize=slack_init,
                     bounds=slack_bounds)
    decl.declare_var('p_slack_neg',
                     model=model,
                     index_set=bus_attrs['names'],
                     initialize=slack_init,
                     bounds=slack_bounds)
    p_rhs_kwargs = {
        'include_feasibility_slack_pos': 'p_slack_pos',
        'include_feasibility_slack_neg': 'p_slack_neg'
    }

    p_penalty = penalty * (
        max([gen_attrs['p_cost'][k]['values'][1]
             for k in gen_attrs['names']]) + 1)

    penalty_expr = sum(
        p_penalty * (model.p_slack_pos[bus_name] + model.p_slack_neg[bus_name])
        for bus_name in bus_attrs['names'])
    return p_rhs_kwargs, penalty_expr
Ejemplo n.º 3
0
def _include_system_feasibility_slack(model, bus_p_loads, gen_attrs,
                                      p_marginal_slack_penalty):
    import egret.model_library.decl as decl
    load = sum(bus_p_loads.values())

    over_gen_bounds = (0,
                       tx_utils.over_gen_limit(load, gen_attrs['names'],
                                               gen_attrs['p_max']))
    decl.declare_var('p_over_generation',
                     model=model,
                     index_set=None,
                     initialize=0.,
                     bounds=over_gen_bounds)

    load_shed_bounds = (0,
                        tx_utils.load_shed_limit(load, gen_attrs['names'],
                                                 gen_attrs['p_min']))
    decl.declare_var('p_load_shed',
                     model=model,
                     index_set=None,
                     initialize=0.,
                     bounds=load_shed_bounds)
    p_rhs_kwargs = {
        'include_feasibility_load_shed': 'p_load_shed',
        'include_feasibility_over_generation': 'p_over_generation'
    }
    penalty_expr = p_marginal_slack_penalty * (model.p_load_shed +
                                               model.p_over_generation)
    return p_rhs_kwargs, penalty_expr
Ejemplo n.º 4
0
def _include_system_feasibility_slack(model,
                                      gen_attrs,
                                      bus_p_loads,
                                      penalty=1000):
    import egret.model_library.decl as decl
    slack_init = 0
    slack_bounds = (0, sum(bus_p_loads.values()))
    decl.declare_var('p_slack_pos',
                     model=model,
                     index_set=None,
                     initialize=slack_init,
                     bounds=slack_bounds)
    decl.declare_var('p_slack_neg',
                     model=model,
                     index_set=None,
                     initialize=slack_init,
                     bounds=slack_bounds)
    p_rhs_kwargs = {
        'include_feasibility_slack_pos': 'p_slack_pos',
        'include_feasibility_slack_neg': 'p_slack_neg'
    }

    p_penalty = penalty * (
        max([gen_attrs['p_cost'][k]['values'][1]
             for k in gen_attrs['names']]) + 1)

    penalty_expr = p_penalty * (model.p_slack_pos + model.p_slack_neg)
    return p_rhs_kwargs, penalty_expr
Ejemplo n.º 5
0
def declare_var_ij_aggregation_at_bus(model, index_set, **kwargs):
    """
    Create a variable for the aggregated imaginary current at a bus
    """
    decl.declare_var('ij_aggregation_at_bus',
                     model=model,
                     index_set=index_set,
                     **kwargs)
Ejemplo n.º 6
0
def declare_var_pfi_slack_neg(model, index_set, **kwargs):
    """
    Create the negative slack variable for the real part of power flow
    throught an interface
    """
    decl.declare_var('pfi_slack_neg',
                     model=model,
                     index_set=index_set,
                     **kwargs)
Ejemplo n.º 7
0
def declare_var_pf_slack_neg(model, index_set, **kwargs):
    """
    Create the negative slack variable for the real part of power flow
    in the "from" end of the transmission line
    """
    decl.declare_var('pf_slack_neg',
                     model=model,
                     index_set=index_set,
                     **kwargs)
Ejemplo n.º 8
0
def _include_feasibility_slack(model, bus_names, bus_p_loads, bus_q_loads,
                               gens_by_bus, gen_attrs,
                               p_marginal_slack_penalty, q_marginal_slack_penalty):
    
    import egret.model_library.decl as decl

    p_over_gen_bounds = {k: (0, tx_utils.over_gen_limit(bus_p_loads[k], gens_by_bus[k], gen_attrs['p_max'])) for k in bus_names}
    decl.declare_var('p_over_generation', model=model, index_set=bus_names,
                     initialize=0., bounds=p_over_gen_bounds
                     )

    p_load_shed_bounds  = {k: (0, tx_utils.load_shed_limit(bus_p_loads[k], gens_by_bus[k], gen_attrs['p_min'])) for k in bus_names}
    decl.declare_var('p_load_shed', model=model, index_set=bus_names,
                     initialize=0., bounds=p_load_shed_bounds
                     )

    q_over_gen_bounds = {k: (0, tx_utils.over_gen_limit(bus_q_loads[k], gens_by_bus[k], gen_attrs['q_max'])) for k in bus_names}
    decl.declare_var('q_over_generation', model=model, index_set=bus_names,
                     initialize=0., bounds=q_over_gen_bounds
                     )

    q_load_shed_bounds  = {k: (0, tx_utils.load_shed_limit(bus_q_loads[k], gens_by_bus[k], gen_attrs['q_min'])) for k in bus_names}
    decl.declare_var('q_load_shed', model=model, index_set=bus_names,
                     initialize=0., bounds=q_load_shed_bounds
                     )
    p_rhs_kwargs = {'include_feasibility_load_shed':'p_load_shed', 'include_feasibility_over_generation':'p_over_generation'}
    q_rhs_kwargs = {'include_feasibility_load_shed':'q_load_shed', 'include_feasibility_over_generation':'q_over_generation'}

    penalty_expr = sum(p_marginal_slack_penalty * (model.p_over_generation[bus_name] + model.p_load_shed[bus_name])
                     + q_marginal_slack_penalty * (model.q_over_generation[bus_name] + model.q_load_shed[bus_name])
                    for bus_name in bus_names)
    return p_rhs_kwargs, q_rhs_kwargs, penalty_expr
Ejemplo n.º 9
0
def declare_ineq_soc(model, index_set, use_outer_approximation=False):
    """
    create the constraint for the second order cone
    """
    m = model
    if not use_outer_approximation:
        con_set = decl.declare_set("_con_ineq_soc", model, index_set)
        m.ineq_soc = pe.Constraint(con_set)
        for from_bus, to_bus in con_set:
            m.ineq_soc[(from_bus, to_bus)] = m.c[from_bus, to_bus]**2 + m.s[
                from_bus, to_bus]**2 <= m.vmsq[from_bus] * m.vmsq[to_bus]
    else:
        if not coramin_available:
            raise ImportError(
                'Cannot create SOC relaxation with outer approximation unless coramin is available.'
            )
        """
        in order to use outer approximation, we have to reformulate 
        
        c**2 + s**2 <= vmsq[from_bus] * vmsq[to_bus]
        
        to
        
        (c**2 + s**2 + z1**2) ** 0.5 <= z2
        z1 = 0.5 * (vmsq[from_bus] - vmsq[to_bus])
        z2 = 0.5 * (vmsq[from_bus] + vmsq[to_bus]) 
        """
        con_set = decl.declare_set("_con_ineq_soc", model, index_set)
        decl.declare_var('_z1', model=model, index_set=con_set)
        decl.declare_var('_z2', model=model, index_set=con_set)
        m._eq_z1 = pe.Constraint(con_set)
        m._eq_z2 = pe.Constraint(con_set)
        m.ineq_soc_OA = coramin.relaxations.MultivariateRelaxation(con_set)
        for from_bus, to_bus in con_set:
            m._eq_z1[from_bus,
                     to_bus] = m._z1[from_bus,
                                     to_bus] == 0.5 * (m.vmsq[from_bus] -
                                                       m.vmsq[to_bus])
            m._eq_z2[from_bus,
                     to_bus] = m._z2[from_bus,
                                     to_bus] == 0.5 * (m.vmsq[from_bus] +
                                                       m.vmsq[to_bus])
            fbbt(m._eq_z1[from_bus, to_bus])
            fbbt(m._eq_z2[from_bus, to_bus])
            m.ineq_soc_OA[from_bus, to_bus].build(
                aux_var=m._z2[from_bus, to_bus],
                shape=coramin.utils.FunctionShape.CONVEX,
                f_x_expr=(m.c[from_bus, to_bus]**2 + m.s[from_bus, to_bus]**2 +
                          m._z1[from_bus, to_bus]**2)**0.5)
Ejemplo n.º 10
0
def _include_system_feasibility_slack(model, gen_attrs, bus_p_loads,
                                      p_marginal_slack_penalty):
    import egret.model_library.decl as decl
    slack_init = 0
    slack_bounds = (0, sum(bus_p_loads.values()))
    decl.declare_var('p_over_generation',
                     model=model,
                     index_set=None,
                     initialize=slack_init,
                     bounds=slack_bounds)
    decl.declare_var('p_load_shed',
                     model=model,
                     index_set=None,
                     initialize=slack_init,
                     bounds=slack_bounds)
    p_rhs_kwargs = {
        'include_feasibility_slack_pos': 'p_over_generation',
        'include_feasibility_slack_neg': 'p_load_shed'
    }

    penalty_expr = p_marginal_slack_penalty * (model.p_over_generation +
                                               model.p_load_shed)
    return p_rhs_kwargs, penalty_expr
Ejemplo n.º 11
0
def declare_var_pfl(model, index_set, **kwargs):
    """
    Create variable for the real part of the power loss in the transmission
    line
    """
    decl.declare_var('pfl', model=model, index_set=index_set, **kwargs)
Ejemplo n.º 12
0
def declare_var_s(model, index_set, **kwargs):
    """
    Create an auxiliary variable for vf * vt * sin(theta_f - theta_t)
    """
    decl.declare_var('s', model=model, index_set=index_set, **kwargs)
Ejemplo n.º 13
0
def declare_var_ifr(model, index_set, **kwargs):
    """
    Create variable for the real part of the current flow in the "from"
    end of the transmission line
    """
    decl.declare_var('ifr', model=model, index_set=index_set, **kwargs)
Ejemplo n.º 14
0
def declare_var_qg(model, index_set, **kwargs):
    """
    Create a variable for the reactive component of the power at a generator
    """
    decl.declare_var('qg', model=model, index_set=index_set, **kwargs)
Ejemplo n.º 15
0
Archivo: bus.py Proyecto: wlinz3/Egret
def declare_var_va(model, index_set, **kwargs):
    """
    Create variable for the phase angle of the voltage at a bus
    """
    decl.declare_var('va', model=model, index_set=index_set, **kwargs)
Ejemplo n.º 16
0
Archivo: bus.py Proyecto: wlinz3/Egret
def declare_var_vj(model, index_set, **kwargs):
    """
    Create variable for the imaginary component of the voltage at a bus
    """
    decl.declare_var('vj', model=model, index_set=index_set, **kwargs)
Ejemplo n.º 17
0
Archivo: bus.py Proyecto: wlinz3/Egret
def declare_var_vm(model, index_set, **kwargs):
    """
    Create variable for the voltage magnitude of the voltage at a bus
    """
    decl.declare_var('vm', model=model, index_set=index_set, **kwargs)
Ejemplo n.º 18
0
def create_hot_start_lpac_model(model_data,
                                voltages,
                                lower_bound=-pi / 3,
                                upper_bound=pi / 3,
                                cosine_segment_count=20,
                                include_feasibility_slack=False,
                                mode="uniform"):
    """
	The hot start LPAC model assumes that voltages are known, e.g. from an AC base point solution.
	"""
    ###Grid data
    md = model_data.clone_in_service()
    tx_utils.scale_ModelData_to_pu(md, inplace=True)

    gens = dict(md.elements(element_type='generator'))
    buses = dict(md.elements(element_type='bus'))
    branches = dict(md.elements(element_type='branch'))
    loads = dict(md.elements(element_type='load'))
    shunts = dict(md.elements(element_type='shunt'))

    gen_attrs = md.attributes(element_type='generator')
    bus_attrs = md.attributes(element_type='bus')
    branch_attrs = md.attributes(element_type='branch')

    inlet_branches_by_bus, outlet_branches_by_bus = \
           tx_utils.inlet_outlet_branches_by_bus(branches, buses)

    gens_by_bus = tx_utils.gens_by_bus(buses, gens)

    model = pe.ConcreteModel()

    ###declare (and fix) the voltage magnitudes and squares of voltage magnitudes

    bus_voltage_magnitudes = voltages  #Assumes voltages is given as a dictionary
    libbus.declare_var_vm(model,
                          bus_attrs['names'],
                          initialize=bus_voltage_magnitudes)
    model.vm.fix()

    libbus.declare_var_vmsq(
        model=model,
        index_set=bus_attrs['names'],
        initialize={k: v**2
                    for k, v in bus_attrs['vm'].items()},
        bounds=zip_items({k: v**2
                          for k, v in bus_attrs['v_min'].items()},
                         {k: v**2
                          for k, v in bus_attrs['v_max'].items()}))

    ### declare the polar voltages

    libbus.declare_var_va(model,
                          bus_attrs['names'],
                          initialize=bus_attrs['va'])

    ### declare the cosine approximation variables
    cos_hat_bounds = {k: (0, 1) for k in branch_attrs['names']}
    decl.declare_var('cos_hat',
                     model,
                     branch_attrs['names'],
                     bounds=cos_hat_bounds)

    ### fix the reference bus
    ref_bus = md.data['system']['reference_bus']
    #ref_angle = md.data['system']['reference_bus_angle']
    model.va[ref_bus].fix(radians(0.0))

    ### declare the fixed shunts at the buses
    bus_bs_fixed_shunts, bus_gs_fixed_shunts = tx_utils.dict_of_bus_fixed_shunts(
        buses, shunts)

    ### declare (and fix) the loads at the buses
    bus_p_loads, bus_q_loads = tx_utils.dict_of_bus_loads(buses, loads)

    libbus.declare_var_pl(model, bus_attrs['names'], initialize=bus_p_loads)
    libbus.declare_var_ql(model, bus_attrs['names'], initialize=bus_q_loads)
    model.pl.fix()
    model.ql.fix()

    ### include the feasibility slack for the bus balances
    p_rhs_kwargs = {}
    q_rhs_kwargs = {}
    if include_feasibility_slack:
        p_rhs_kwargs, q_rhs_kwargs, penalty_expr = _include_feasibility_slack(
            model, bus_attrs, gen_attrs, bus_p_loads, bus_q_loads)

### declare the generator real and reactive power
    pg_init = {
        k: (gen_attrs['p_min'][k] + gen_attrs['p_max'][k]) / 2.0
        for k in gen_attrs['pg']
    }
    libgen.declare_var_pg(model,
                          gen_attrs['names'],
                          initialize=pg_init,
                          bounds=zip_items(gen_attrs['p_min'],
                                           gen_attrs['p_max']))

    qg_init = {
        k: (gen_attrs['q_min'][k] + gen_attrs['q_max'][k]) / 2.0
        for k in gen_attrs['qg']
    }
    libgen.declare_var_qg(model,
                          gen_attrs['names'],
                          initialize=qg_init,
                          bounds=zip_items(gen_attrs['q_min'],
                                           gen_attrs['q_max']))

    ### declare the current flows in the branches
    vr_init = {
        k: bus_attrs['vm'][k] * pe.cos(bus_attrs['va'][k])
        for k in bus_attrs['vm']
    }
    vj_init = {
        k: bus_attrs['vm'][k] * pe.sin(bus_attrs['va'][k])
        for k in bus_attrs['vm']
    }
    s_max = {k: branches[k]['rating_long_term'] for k in branches.keys()}
    s_lbub = dict()
    for k in branches.keys():
        if s_max[k] is None:
            s_lbub[k] = (None, None)
        else:
            s_lbub[k] = (-s_max[k], s_max[k])
    pf_bounds = s_lbub
    pt_bounds = s_lbub
    qf_bounds = s_lbub
    qt_bounds = s_lbub
    pf_init = dict()
    pt_init = dict()
    qf_init = dict()
    qt_init = dict()
    for branch_name, branch in branches.items():
        from_bus = branch['from_bus']
        to_bus = branch['to_bus']
        y_matrix = tx_calc.calculate_y_matrix_from_branch(branch)
        ifr_init = tx_calc.calculate_ifr(vr_init[from_bus], vj_init[from_bus],
                                         vr_init[to_bus], vj_init[to_bus],
                                         y_matrix)
        ifj_init = tx_calc.calculate_ifj(vr_init[from_bus], vj_init[from_bus],
                                         vr_init[to_bus], vj_init[to_bus],
                                         y_matrix)
        itr_init = tx_calc.calculate_itr(vr_init[from_bus], vj_init[from_bus],
                                         vr_init[to_bus], vj_init[to_bus],
                                         y_matrix)
        itj_init = tx_calc.calculate_itj(vr_init[from_bus], vj_init[from_bus],
                                         vr_init[to_bus], vj_init[to_bus],
                                         y_matrix)
        pf_init[branch_name] = tx_calc.calculate_p(ifr_init, ifj_init,
                                                   vr_init[from_bus],
                                                   vj_init[from_bus])
        pt_init[branch_name] = tx_calc.calculate_p(itr_init, itj_init,
                                                   vr_init[to_bus],
                                                   vj_init[to_bus])
        qf_init[branch_name] = tx_calc.calculate_q(ifr_init, ifj_init,
                                                   vr_init[from_bus],
                                                   vj_init[from_bus])
        qt_init[branch_name] = tx_calc.calculate_q(itr_init, itj_init,
                                                   vr_init[to_bus],
                                                   vj_init[to_bus])

    libbranch.declare_var_pf(model=model,
                             index_set=branch_attrs['names'],
                             initialize=pf_init,
                             bounds=pf_bounds)
    libbranch.declare_var_pt(model=model,
                             index_set=branch_attrs['names'],
                             initialize=pt_init,
                             bounds=pt_bounds)
    libbranch.declare_var_qf(model=model,
                             index_set=branch_attrs['names'],
                             initialize=qf_init,
                             bounds=qf_bounds)
    libbranch.declare_var_qt(model=model,
                             index_set=branch_attrs['names'],
                             initialize=qt_init,
                             bounds=qt_bounds)

    ####################
    #Constraints
    ####################

    ###Balance equations in a bus

    #p balance

    libbus.declare_eq_p_balance(model=model,
                                index_set=bus_attrs['names'],
                                bus_p_loads=bus_p_loads,
                                gens_by_bus=gens_by_bus,
                                bus_gs_fixed_shunts=bus_gs_fixed_shunts,
                                inlet_branches_by_bus=inlet_branches_by_bus,
                                outlet_branches_by_bus=outlet_branches_by_bus,
                                **p_rhs_kwargs)

    #q balance

    libbus.declare_eq_q_balance(model=model,
                                index_set=bus_attrs['names'],
                                bus_q_loads=bus_q_loads,
                                gens_by_bus=gens_by_bus,
                                bus_bs_fixed_shunts=bus_bs_fixed_shunts,
                                inlet_branches_by_bus=inlet_branches_by_bus,
                                outlet_branches_by_bus=outlet_branches_by_bus,
                                **q_rhs_kwargs)

    ### Power in a branch

    branch_con_set = decl.declare_set('_con_eq_p_q_lpac_branch_power', model,
                                      branch_attrs['names'])

    model.eq_pf_branch_t = pe.Constraint(branch_con_set)
    model.eq_pt_branch_t = pe.Constraint(branch_con_set)
    model.eq_qf_branch_t = pe.Constraint(branch_con_set)
    model.eq_qt_branch_t = pe.Constraint(branch_con_set)

    for branch_name in branch_con_set:
        branch = branches[branch_name]

        from_bus = branch['from_bus']
        to_bus = branch['to_bus']

        g = tx_calc.calculate_conductance(branch)
        b = tx_calc.calculate_susceptance(branch)

        model.eq_pf_branch_t[branch_name] = \
         model.pf[branch_name] == \
         g*model.vmsq[from_bus] - model.vm[from_bus]*model.vm[to_bus]*(g * model.cos_hat[branch_name] + b * (model.va[from_bus] - model.va[to_bus]))

        model.eq_pt_branch_t[branch_name] = \
         model.pt[branch_name] == \
         g*model.vmsq[to_bus] - model.vm[from_bus]*model.vm[to_bus]*(g * model.cos_hat[branch_name] + b * (model.va[to_bus] - model.va[from_bus]))

        model.eq_qf_branch_t[branch_name] = \
         model.qf[branch_name] == \
         -b*model.vmsq[from_bus] - model.vm[from_bus]*model.vm[to_bus]*(g*(model.va[from_bus] - model.va[to_bus]) - b*model.cos_hat[branch_name])

        model.eq_qt_branch_t[branch_name] = \
         model.qt[branch_name] == \
         -b*model.vmsq[to_bus] - model.vm[from_bus]*model.vm[to_bus]*(g*(model.va[to_bus] - model.va[from_bus]) - b*model.cos_hat[branch_name])

### Piecewise linear cosine constraints

    model.N = pe.Set(initialize=list(range(cosine_segment_count + 1)))

    declare_pwl_cosine_bounds(model=model,
                              index_set=branch_attrs['names'],
                              branches=branches,
                              lower_bound=lower_bound,
                              upper_bound=upper_bound,
                              cosine_segment_count=cosine_segment_count,
                              mode=mode)

    ### Objective is to maximize cosine hat variables

    obj_expr = sum(model.cos_hat[branch_name]
                   for branch_name in branch_attrs['names'])

    if include_feasibility_slack:
        obj_expr += penalty_expr

    model.obj = pe.Objective(expr=obj_expr)

    return model, md
Ejemplo n.º 19
0
Archivo: bus.py Proyecto: wlinz3/Egret
def declare_var_vmsq(model, index_set, **kwargs):
    """
    Create auxiliary variable for the voltage magnitude squared at a bus
    """
    decl.declare_var('vmsq', model=model, index_set=index_set, **kwargs)
def create_master(model_data, omega, k=1):
    """
    Create the upper-level (master) of the stochastic bilevel problem

    Arguments:
        model_data: An Egret dict of dict that stores data for the power system
        omega: A dict of scenario name <key> and probability per scenario <value>
        where the probabilities add to 1
        k: A positive integer indicating the number of relays that can be attacked

    Returns: Tuple with the following values:
        model: A Pyomo model representing the algebraic form of the bilevel problem
        md: The model_data object associated to the model
    """
    ### power system data
    md = model_data

    ### create dictionaries of object sets
    relays = dict(md.elements(element_type='relay'))
    gens = dict(md.elements(element_type='generator'))
    buses = dict(md.elements(element_type='bus'))
    loads = dict(md.elements(element_type='load'))
    branches = dict(md.elements(element_type='branch'))

    ### create dictionaries across object attributes for an object of the same set type
    relay_attrs = md.attributes(element_type='relay')
    gen_attrs = md.attributes(element_type='generator')
    branch_attrs = md.attributes(element_type='branch')

    ### declare new Pyomo model
    model = pe.ConcreteModel()

    ### scenarios
    scenarios = omega.keys()

    ### declare (and fix) the loads at the buses
    bus_p_loads, _ = tx_utils.dict_of_bus_loads(buses, loads)
    buses_with_loads = list(k for k in bus_p_loads.keys()
                            if bus_p_loads[k] != 0.)

    ### relay-to-power-device mappings
    relay_branches = utils.dict_of_relay_branches(relays, branches)
    branch_relays = utils.dict_of_branch_relays(relays, branches)
    relay_branch_tuple = utils.relay_branch_tuple(relay_branches)
    relay_gens = utils.dict_of_relay_gens(relays, gens)
    gen_relays = utils.dict_of_gen_relays(relays, gens)
    relay_gen_tuple = utils.relay_branch_tuple(relay_gens)
    relay_loads = utils.dict_of_relay_loads(relays, loads, buses_with_loads)
    load_relays = utils.dict_of_load_relays(relays, buses_with_loads)
    relay_load_tuple = utils.relay_branch_tuple(relay_loads)

    ### upper-level (attacker) variables
    scenarios_loads = pe.Set(initialize=scenarios) * pe.Set(
        initialize=buses_with_loads)
    decl.declare_var('load_shed',
                     model,
                     scenarios_loads,
                     initialize=0.0,
                     domain=pe.NonNegativeReals)
    decl.declare_var('delta',
                     model,
                     relay_attrs['names'],
                     domain=pe.Binary,
                     bounds=(0, 1))  # relays compromised
    decl.declare_var('u',
                     model,
                     buses_with_loads,
                     domain=pe.Binary,
                     bounds=(0, 1))  # load available
    decl.declare_var('v',
                     model,
                     gen_attrs['names'],
                     domain=pe.Binary,
                     bounds=(0, 1))  # generator available
    decl.declare_var('w',
                     model,
                     branch_attrs['names'],
                     domain=pe.Binary,
                     bounds=(0, 1))  # line available

    ### upper-level constraints
    cons.declare_budget(
        model, k,
        relays)  # note that all k are costed equally in current implementation
    cons.declare_load_compromised(model, relay_load_tuple)
    cons.declare_load_uncompromised(model, buses_with_loads, load_relays)
    cons.declare_branch_compromised(model, relay_branch_tuple)
    cons.declare_branch_uncompromised(model, branch_attrs['names'],
                                      branch_relays)
    cons.declare_gen_compromised(model, relay_gen_tuple)
    cons.declare_gen_uncompromised(model, gen_attrs['names'], gen_relays)

    ### upper-level objective for stochastic interdiction problem (opposite to lower-level objective)
    model.obj = pe.Objective(expr=sum(omega[p]['probability'] *
                                      model.load_shed[p, l]
                                      for (p, l) in scenarios_loads),
                             sense=pe.maximize)

    return model, md
Ejemplo n.º 21
0
def declare_var_pt(model, index_set, **kwargs):
    """
    Create variable for the real part of the power flow in the "to"
    end of the transmission line
    """
    decl.declare_var('pt', model=model, index_set=index_set, **kwargs)
Ejemplo n.º 22
0
def create_explicit_subproblem(model,
                               subproblem,
                               model_data,
                               include_angle_diff_limits=False,
                               include_bigm=False):
    ### power system data
    md = model_data

    ### create dictionaries of object sets
    gens = dict(md.elements(element_type='generator'))
    buses = dict(md.elements(element_type='bus'))
    branches = dict(md.elements(element_type='branch'))
    loads = dict(md.elements(element_type='load'))
    shunts = dict(md.elements(element_type='shunt'))

    ### create dictionaries across object attributes for an object of the same set type
    gen_attrs = md.attributes(element_type='generator')
    bus_attrs = md.attributes(element_type='bus')
    branch_attrs = md.attributes(element_type='branch')

    inlet_branches_by_bus, outlet_branches_by_bus = \
        tx_utils.inlet_outlet_branches_by_bus(branches, buses)
    gens_by_bus = tx_utils.gens_by_bus(buses, gens)

    ### declare (and fix) the loads at the buses
    bus_p_loads, _ = tx_utils.dict_of_bus_loads(buses, loads)
    buses_with_loads = list(k for k in bus_p_loads.keys()
                            if bus_p_loads[k] != 0.)

    ### declare load shed variables
    decl.declare_var('load_shed',
                     subproblem,
                     buses_with_loads,
                     initialize=0.0,
                     domain=pe.NonNegativeReals)

    #libbus.declare_var_pl(model.subproblem, bus_attrs['names'], initialize=bus_p_loads)
    #model.subproblem.pl.fix()
    subproblem.pl = bus_p_loads

    ### declare the fixed shunts at the buses
    _, bus_gs_fixed_shunts = tx_utils.dict_of_bus_fixed_shunts(buses, shunts)

    ### declare the polar voltages
    va_bounds = {k: (-pi, pi) for k in bus_attrs['va']}
    va_init = {k: bus_attrs['va'][k] * (pi / 180) for k in bus_attrs['va']}
    libbus.declare_var_va(subproblem,
                          bus_attrs['names'],
                          initialize=bus_attrs['va'],
                          bounds=va_bounds)

    ### fix the reference bus
    ref_bus = md.data['system']['reference_bus']
    ref_angle = md.data['system']['reference_bus_angle']
    subproblem.va[ref_bus].fix(radians(ref_angle))

    ### declare the generator real power
    pg_init = {
        k: (gen_attrs['p_min'][k] + gen_attrs['p_max'][k]) / 2.0
        for k in gen_attrs['pg']
    }
    libgen.declare_var_pg(subproblem, gen_attrs['names'], initialize=pg_init)

    ### declare the current flows in the branches
    vr_init = {
        k: bus_attrs['vm'][k] * pe.cos(bus_attrs['va'][k])
        for k in bus_attrs['vm']
    }
    vj_init = {
        k: bus_attrs['vm'][k] * pe.sin(bus_attrs['va'][k])
        for k in bus_attrs['vm']
    }
    pf_init = dict()
    for branch_name, branch in branches.items():
        from_bus = branch['from_bus']
        to_bus = branch['to_bus']
        y_matrix = tx_calc.calculate_y_matrix_from_branch(branch)
        ifr_init = tx_calc.calculate_ifr(vr_init[from_bus], vj_init[from_bus],
                                         vr_init[to_bus], vj_init[to_bus],
                                         y_matrix)
        ifj_init = tx_calc.calculate_ifj(vr_init[from_bus], vj_init[from_bus],
                                         vr_init[to_bus], vj_init[to_bus],
                                         y_matrix)
        pf_init[branch_name] = tx_calc.calculate_p(ifr_init, ifj_init,
                                                   vr_init[from_bus],
                                                   vj_init[from_bus])

    libbranch.declare_var_pf(model=subproblem,
                             index_set=branch_attrs['names'],
                             initialize=pf_init)

    # need to include variable references on subproblem to variables, which exist on the master block
    #bi.components.varref(subproblem, origin = model)
    subproblem.add_component("u", Reference(model.u))
    subproblem.add_component("v", Reference(model.v))
    subproblem.add_component("w", Reference(model.w))
    if include_bigm:
        # create big-M
        _create_bigm(subproblem, md)
        ### declare the branch power flow disjuncts
        subcons.declare_eq_branch_power_btheta_approx_bigM(
            model=subproblem,
            index_set=branch_attrs['names'],
            branches=branches)

        ### declare the real power flow limits
        p_max = {k: branches[k]['rating_long_term'] for k in branches.keys()}
        subcons.declare_ineq_p_branch_thermal_lbub_switch(
            model=subproblem,
            index_set=branch_attrs['names'],
            p_thermal_limits=p_max)

    else:
        ### declare the branch power flow with indicator variable in the bilinear term
        subcons.declare_eq_branch_power_btheta_approx_nonlin(
            model=subproblem,
            index_set=branch_attrs['names'],
            branches=branches)

        ### declare the real power flow limits
        p_max = {k: branches[k]['rating_long_term'] for k in branches.keys()}
        libbranch.declare_ineq_p_branch_thermal_lbub(
            model=subproblem,
            index_set=branch_attrs['names'],
            branches=branches,
            p_thermal_limits=p_max,
            approximation_type=ApproximationType.BTHETA)

    ### declare the load shed
    subcons.declare_ineq_load_shed(model=subproblem,
                                   index_set=buses_with_loads)

    ### declare the generator compromised
    subcons.declare_ineq_gen(model=subproblem,
                             index_set=gen_attrs['names'],
                             gens=gens)

    ### declare the p balance
    rhs_kwargs = {'include_feasibility_slack_neg': 'load_shed'}
    libbus.declare_eq_p_balance_dc_approx(
        model=subproblem,
        index_set=bus_attrs['names'],
        bus_p_loads=bus_p_loads,
        gens_by_bus=gens_by_bus,
        bus_gs_fixed_shunts=bus_gs_fixed_shunts,
        inlet_branches_by_bus=inlet_branches_by_bus,
        outlet_branches_by_bus=outlet_branches_by_bus,
        approximation_type=ApproximationType.BTHETA,
        **rhs_kwargs)

    ### declare angle difference limits on interconnected buses
    if include_angle_diff_limits:
        libbranch.declare_ineq_angle_diff_branch_lbub(
            model=subproblem,
            index_set=branch_attrs['names'],
            branches=branches,
            coordinate_type=CoordinateType.POLAR)

    ### lower-level objective for interdiction problem (opposite to upper-level objective)
    subproblem.obj = pe.Objective(expr=sum(subproblem.load_shed[l]
                                           for l in buses_with_loads),
                                  sense=pe.minimize)

    return model, md
Ejemplo n.º 23
0
def declare_var_itj(model, index_set, **kwargs):
    """
    Create variable for the imaginary part of the current flow in the "to"
    end of the transmission line
    """
    decl.declare_var('itj', model=model, index_set=index_set, **kwargs)
Ejemplo n.º 24
0
def create_master(model_data, k=1):
    """
    Create the upper-level (master) of the bilevel problem

    Arguments:
        model_data: An Egret dict of dict that stores data for the power system
        k: A positive integer indicating the number of relays that can be attacked

    Returns: Tuple with the following values:
        model: A Pyomo model representing the algebraic form of the bilevel problem
        md: The model_data object associated to the model
    """
    ### power system data
    md = model_data

    ### create dictionaries of object sets
    gens = dict(md.elements(element_type='generator'))
    buses = dict(md.elements(element_type='bus'))
    loads = dict(md.elements(element_type='load'))
    branches = dict(md.elements(element_type='branch'))

    ### create dictionaries across object attributes for an object of the same set type
    bus_attrs = md.attributes(element_type='bus')
    gen_attrs = md.attributes(element_type='generator')
    branch_attrs = md.attributes(element_type='branch')

    ### declare new Pyomo model
    model = pe.ConcreteModel()

    ### declare (and fix) the loads at the buses
    bus_p_loads, _ = tx_utils.dict_of_bus_loads(buses, loads)
    buses_with_loads = list(k for k in bus_p_loads.keys()
                            if bus_p_loads[k] != 0.)
    ### upper-level (attacker) variables
    decl.declare_var('load_shed',
                     model,
                     buses_with_loads,
                     initialize=0.0,
                     domain=pe.NonNegativeReals)
    decl.declare_var('delta_k', model, branch_attrs['names'],
                     domain=pe.Binary)  # line compromised
    decl.declare_var('delta_g', model, gen_attrs['names'],
                     domain=pe.Binary)  # gen compromised
    decl.declare_var('delta_b', model, bus_attrs['names'],
                     domain=pe.Binary)  # bus compromised
    decl.declare_var('u', model, buses_with_loads,
                     domain=pe.Binary)  # load available
    decl.declare_var('v', model, gen_attrs['names'],
                     domain=pe.Binary)  # generator available
    decl.declare_var('w', model, branch_attrs['names'],
                     domain=pe.Binary)  # line available

    ### upper-level constraints
    cons.declare_component_budget(model, k, branch_attrs['name'],\
        gen_attrs['name'], bus_attrs['names']) # note that all k are costed equally in current implementation
    cons.declare_load_compromised(model, relay_load_tuple)
    cons.declare_load_uncompromised(model, buses_with_loads, load_relays)
    cons.declare_branch_compromised(model, relay_branch_tuple)
    cons.declare_branch_uncompromised(model, branch_attrs['names'],
                                      branch_relays)
    cons.declare_gen_compromised(model, relay_gen_tuple)
    cons.declare_gen_uncompromised(model, gen_attrs['names'], gen_relays)

    ### upper-level objective for interdiction problem (opposite to lower-level objective)
    model.obj = pe.Objective(expr=sum(model.load_shed[l]
                                      for l in buses_with_loads),
                             sense=pe.maximize)

    return model, md
Ejemplo n.º 25
0
def declare_var_dva(model, index_set, **kwargs):
    """
    Create variable or the angle difference between interconnected bus pairs
    """
    decl.declare_var('dva', model=model, index_set=index_set, **kwargs)
Ejemplo n.º 26
0
Archivo: bus.py Proyecto: wlinz3/Egret
def declare_var_pl(model, index_set, **kwargs):
    """
    Create variable for the real power load at a bus
    """
    decl.declare_var('pl', model=model, index_set=index_set, **kwargs)
Ejemplo n.º 27
0
def declare_var_pfi(model, index_set, **kwargs):
    """
    Create variable for the real part of the power flow through an interface
    """
    decl.declare_var('pfi', model=model, index_set=index_set, **kwargs)
Ejemplo n.º 28
0
Archivo: bus.py Proyecto: wlinz3/Egret
def declare_var_p_nw(model, index_set, **kwargs):
    """
    Create variable for the reactive power load at a bus
    """
    decl.declare_var('p_nw', model=model, index_set=index_set, **kwargs)
Ejemplo n.º 29
0
def declare_var_qf(model, index_set, **kwargs):
    """
    Create variable for the imaginary part of the power flow in the "from"
    end of the transmission line
    """
    decl.declare_var('qf', model=model, index_set=index_set, **kwargs)
Ejemplo n.º 30
0
Archivo: bus.py Proyecto: wlinz3/Egret
def declare_var_vr(model, index_set, **kwargs):
    """
    Create variable for the real component of the voltage at a bus
    """
    decl.declare_var('vr', model=model, index_set=index_set, **kwargs)