예제 #1
0
def declare_eq_branch_dva(model, index_set, branches):
    """
    Create the equality constraints for the angle difference
    in the branch
    """
    m = model

    con_set = decl.declare_set("_con_eq_branch_dva_set", model, index_set)

    m.eq_dva_branch = pe.Constraint(con_set)
    for branch_name in con_set:
        branch = branches[branch_name]

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

        shift = 0.0
        if branch['branch_type'] == 'transformer':
            shift = math.radians(branch['transformer_phase_shift'])

        m.eq_dva_branch[branch_name] = \
            m.dva[branch_name] == \
            m.va[from_bus] - m.va[to_bus] + shift
예제 #2
0
def declare_ineq_p_branch_thermal_lbub_switch(model, index_set,
                                              p_thermal_limits):
    """
    Create the inequality constraints for the branch thermal limits
    based on the power variables or expressions.
    """
    m = model
    con_set = decl.declare_set('_con_ineq_p_branch_thermal_lbub',
                               model=model,
                               index_set=index_set)

    m.ineq_pf_branch_thermal_lb = pe.Constraint(con_set)
    m.ineq_pf_branch_thermal_ub = pe.Constraint(con_set)

    for branch_name in con_set:
        if p_thermal_limits[branch_name] is None:
            continue

        m.ineq_pf_branch_thermal_lb[branch_name] = \
            -p_thermal_limits[branch_name]*m.w[branch_name] <= m.pf[branch_name]

        m.ineq_pf_branch_thermal_ub[branch_name] = \
            m.pf[branch_name] <= p_thermal_limits[branch_name]*m.w[branch_name]
예제 #3
0
def declare_eq_branch_power_dc_approx(
        model,
        index_set,
        branches,
        approximation_type=ApproximationType.BTHETA):
    """
    Create the equality constraints for power (from DC approximation)
    in the branch
    """
    assert (approximation_type == ApproximationType.BTHETA
            and "Only the B-Theta approximation has been implemented.")
    m = model

    con_set = decl.declare_set("_con_eq_branch_power_dc_approx_set", model,
                               index_set)

    m.eq_pf_branch = pe.Constraint(con_set)
    for branch_name in con_set:
        branch = branches[branch_name]
        if not branch['in_service']:
            continue

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

        x = branch['reactance']
        tau = 1.0
        shift = 0.0

        if branch['branch_type'] == 'transformer':
            tau = branch['transformer_tap_ratio']
            shift = math.radians(branch['transformer_phase_shift'])

        b = 1 / (tau * x)
        m.eq_pf_branch[branch_name] = \
            m.pf[branch_name] == \
            b * (m.va[from_bus] - m.va[to_bus] - shift)
예제 #4
0
파일: bus.py 프로젝트: wlinz3/Egret
def declare_ineq_vm_bus_lbub(model, index_set, buses, coordinate_type=CoordinateType.POLAR):
    """
    Create the inequalities for the voltage magnitudes from the
    voltage variables
    """
    m = model
    con_set = decl.declare_set('_con_ineq_vm_bus_lbub',
                               model=model, index_set=index_set)

    m.ineq_vm_bus_lb = pe.Constraint(con_set)
    m.ineq_vm_bus_ub = pe.Constraint(con_set)

    if coordinate_type == CoordinateType.POLAR:
        for bus_name in con_set:
            m.ineq_vm_bus_lb[bus_name] = \
                buses[bus_name]['v_min'] <= m.vm[bus_name]
            m.ineq_vm_bus_ub[bus_name] = \
                m.vm[bus_name] <= buses[bus_name]['v_max']
    elif coordinate_type == CoordinateType.RECTANGULAR:
        for bus_name in con_set:
            m.ineq_vm_bus_lb[bus_name] = \
                buses[bus_name]['v_min']**2 <= m.vr[bus_name]**2 + m.vj[bus_name]**2
            m.ineq_vm_bus_ub[bus_name] = \
                m.vr[bus_name]**2 + m.vj[bus_name]**2 <= buses[bus_name]['v_max']**2
예제 #5
0
def declare_expression_pg_operating_cost(model, index_set, p_costs, pw_formulation='delta'):
    """
    Create the Expression objects to represent the operating costs
    for the real power of each of the generators.
    """
    m = model
    expr_set = decl.declare_set('_expr_pg_operating_cost',
                                model=model, index_set=index_set)
    m.pg_operating_cost = pe.Expression(expr_set)

    for gen_name in expr_set:
        if gen_name in p_costs:
            if p_costs[gen_name]['cost_curve_type'] == 'polynomial':
                m.pg_operating_cost[gen_name] = sum(v*m.pg[gen_name]**i for i, v in p_costs[gen_name]['values'].items())
            elif p_costs[gen_name]['cost_curve_type'] == 'piecewise':
                if pw_formulation == 'delta':
                    p_min = m.pg[gen_name].lb
                    p_max = m.pg[gen_name].ub
                    curve = p_costs[gen_name]
                    cleaned_values = tx_utils.validate_and_clean_cost_curve(curve=curve,
                                                                            curve_type='cost_curve',
                                                                            p_min=p_min,
                                                                            p_max=p_max,
                                                                            gen_name=gen_name)
                    expr = cleaned_values[0][1]
                    if len(cleaned_values) > 1:
                        for ndx, ((o1, c1), (o2, c2)) in enumerate(zip(cleaned_values, cleaned_values[1:])):
                            slope = (c2 - c1) / (o2 - o1)
                            expr += slope * m.delta_pg[gen_name, ndx]
                    m.pg_operating_cost[gen_name] = expr
                else:
                    m.pg_operating_cost[gen_name] = m.pg_cost[gen_name]
            else:
                raise ValueError(f"Unrecognized cost_cureve_type: {p_costs[gen_name]['cost_curve_type']}")
        else:
            m.pg_operating_cost[gen_name] = 0
예제 #6
0
def declare_ineq_p_branch_thermal_lbub(model, index_set,
                                        branches, p_thermal_limits,
                                        approximation_type=ApproximationType.BTHETA):
    """
    Create the inequality constraints for the branch thermal limits
    based on the power variables.
    """
    m = model
    con_set = decl.declare_set('_con_ineq_p_branch_thermal_lbub',
                               model=model, index_set=index_set)

    m.ineq_pf_branch_thermal_lb = pe.Constraint(con_set)
    m.ineq_pf_branch_thermal_ub = pe.Constraint(con_set)

    if approximation_type == ApproximationType.BTHETA:
        for branch_name in con_set:
            if p_thermal_limits[branch_name] is None:
                continue

            m.ineq_pf_branch_thermal_lb[branch_name] = \
                -p_thermal_limits[branch_name] <= m.pf[branch_name]

            m.ineq_pf_branch_thermal_ub[branch_name] = \
                m.pf[branch_name] <= p_thermal_limits[branch_name]
예제 #7
0
def declare_ineq_angle_diff_branch_lbub_c_s(model, index_set, branches):
    """
    Create the inequality constraints for the angle difference
    bounds between interconnected buses.
    """
    m = model
    con_set = decl.declare_set('_con_ineq_angle_diff_branch_lbub',
                               model=model,
                               index_set=index_set)

    m.ineq_angle_diff_branch_lb = pe.Constraint(con_set)
    m.ineq_angle_diff_branch_ub = pe.Constraint(con_set)

    for branch_name in con_set:
        from_bus = branches[branch_name]['from_bus']
        to_bus = branches[branch_name]['to_bus']

        m.ineq_angle_diff_branch_lb[branch_name] = (
            math.tan(math.radians(branches[branch_name]['angle_diff_min'])) *
            m.c[(from_bus, to_bus)] <= m.s[(from_bus, to_bus)])
        m.ineq_angle_diff_branch_ub[branch_name] = (
            m.s[(from_bus, to_bus)] <=
            math.tan(math.radians(branches[branch_name]['angle_diff_max'])) *
            m.c[(from_bus, to_bus)])
예제 #8
0
def declare_eq_branch_power_btheta_approx(
        model,
        index_set,
        branches,
        approximation_type=ApproximationType.BTHETA):
    """
    Create the equality constraints for power (from BTHETA approximation)
    in the branch
    """
    m = model

    con_set = decl.declare_set("_con_eq_branch_power_btheta_approx_set", model,
                               index_set)

    m.eq_pf_branch = pe.Constraint(con_set)
    for branch_name in con_set:
        branch = branches[branch_name]

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

        tau = 1.0
        shift = 0.0
        if branch['branch_type'] == 'transformer':
            tau = branch['transformer_tap_ratio']
            shift = math.radians(branch['transformer_phase_shift'])

        if approximation_type == ApproximationType.BTHETA:
            x = branch['reactance']
            b = -1 / (tau * x)
        elif approximation_type == ApproximationType.BTHETA_LOSSES:
            b = tx_calc.calculate_susceptance(branch) / tau

        m.eq_pf_branch[branch_name] = \
            m.pf[branch_name] == \
            b * (m.va[from_bus] - m.va[to_bus] + shift)
예제 #9
0
def declare_ineq_angle_diff_branch_lbub(model,
                                        index_set,
                                        branches,
                                        coordinate_type=CoordinateType.POLAR):
    """
    Create the inequality constraints for the angle difference
    bounds between interconnected buses.
    """
    m = model
    con_set = decl.declare_set('_con_ineq_angle_diff_branch_lbub',
                               model=model,
                               index_set=index_set)

    m.ineq_angle_diff_branch_lb = pe.Constraint(con_set)
    m.ineq_angle_diff_branch_ub = pe.Constraint(con_set)

    if coordinate_type == CoordinateType.POLAR:
        for branch_name in con_set:
            from_bus = branches[branch_name]['from_bus']
            to_bus = branches[branch_name]['to_bus']

            m.ineq_angle_diff_branch_lb[branch_name] = \
                math.radians(branches[branch_name]['angle_diff_min']) <= m.va[from_bus] - m.va[to_bus]
            m.ineq_angle_diff_branch_ub[branch_name] = \
                m.va[from_bus] - m.va[to_bus] <= math.radians(branches[branch_name]['angle_diff_max'])
    elif coordinate_type == CoordinateType.RECTANGULAR:
        for branch_name in con_set:
            from_bus = branches[branch_name]['from_bus']
            to_bus = branches[branch_name]['to_bus']

            m.ineq_angle_diff_branch_lb[branch_name] = \
                math.radians(branches[branch_name]['angle_diff_min']) <= pe.atan(m.vj[from_bus]/m.vr[from_bus]) \
                - pe.atan(m.vj[to_bus]/m.vr[to_bus])
            m.ineq_angle_diff_branch_ub[branch_name] = \
                pe.atan(m.vj[from_bus] / m.vr[from_bus]) \
                - pe.atan(m.vj[to_bus] / m.vr[to_bus]) <= math.radians(branches[branch_name]['angle_diff_max'])
예제 #10
0
def declare_eq_branch_power(model, index_set, branches):
    """
    Create the equality constraints for the real and reactive power
    in the branch
    """
    m = model
    con_set = decl.declare_set("_con_eq_branch_power_set", model, index_set)

    m.eq_pf_branch = pe.Constraint(con_set)
    m.eq_pt_branch = pe.Constraint(con_set)
    m.eq_qf_branch = pe.Constraint(con_set)
    m.eq_qt_branch = pe.Constraint(con_set)
    for branch_name in con_set:
        branch = branches[branch_name]

        from_bus = branch['from_bus']
        to_bus = branch['to_bus']
        vmsq_from_bus = m.vmsq[from_bus]
        vmsq_to_bus = m.vmsq[to_bus]

        g = tx_calc.calculate_conductance(branch)
        b = tx_calc.calculate_susceptance(branch)
        bc = branch['charging_susceptance']
        tau = 1.0
        shift = 0.0

        if branch['branch_type'] == 'transformer':
            tau = branch['transformer_tap_ratio']
            shift = math.radians(branch['transformer_phase_shift'])

        g11 = g / tau**2
        g12 = g * math.cos(shift) / tau
        g21 = g * math.sin(shift) / tau
        g22 = g

        b11 = (b + bc / 2) / tau**2
        b12 = b * math.cos(shift) / tau
        b21 = b * math.sin(shift) / tau
        b22 = b + bc / 2

        m.eq_pf_branch[branch_name] = \
            m.pf[branch_name] == \
            g11 * vmsq_from_bus - \
            (g12 * m.c[(from_bus,to_bus)] +
             g21 * m.s[(from_bus,to_bus)] +
             b12 * m.s[(from_bus,to_bus)] -
             b21 * m.c[(from_bus,to_bus)])

        m.eq_pt_branch[branch_name] = \
            m.pt[branch_name] == \
            g22 * vmsq_to_bus - \
            (g12 * m.c[(from_bus,to_bus)] +
             g21 * m.s[(from_bus,to_bus)] -
             b12 * m.s[(from_bus,to_bus)] +
             b21 * m.c[(from_bus,to_bus)])

        m.eq_qf_branch[branch_name] = \
            m.qf[branch_name] == \
            -b11 * vmsq_from_bus + \
            (b12 * m.c[(from_bus,to_bus)] +
             b21 * m.s[(from_bus,to_bus)] -
             g12 * m.s[(from_bus,to_bus)] +
             g21 * m.c[(from_bus,to_bus)])

        m.eq_qt_branch[branch_name] = \
            m.qt[branch_name] == \
            -b22 * vmsq_to_bus + \
            (b12 * m.c[(from_bus,to_bus)] +
             b21 * m.s[(from_bus,to_bus)] +
             g12 * m.s[(from_bus,to_bus)] -
             g21 * m.c[(from_bus,to_bus)])
예제 #11
0
def declare_eq_branch_power(model,
                            index_set,
                            branches,
                            branch_attrs,
                            coordinate_type=CoordinateType.POLAR):
    """
    Create the equality constraints for the real and reactive power
    in the branch
    """
    m = model

    bus_pairs = zip_items(branch_attrs['from_bus'], branch_attrs['to_bus'])
    unique_bus_pairs = list(set([val for idx, val in bus_pairs.items()]))
    declare_expr_c(model, unique_bus_pairs, coordinate_type)
    declare_expr_s(model, unique_bus_pairs, coordinate_type)

    con_set = decl.declare_set("_con_eq_branch_power_set", model, index_set)

    m.eq_pf_branch = pe.Constraint(con_set)
    m.eq_pt_branch = pe.Constraint(con_set)
    m.eq_qf_branch = pe.Constraint(con_set)
    m.eq_qt_branch = pe.Constraint(con_set)
    for branch_name in con_set:
        branch = branches[branch_name]
        if not branch['in_service']:
            continue

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

        if coordinate_type == CoordinateType.POLAR:
            vmsq_from_bus = m.vm[from_bus]**2
            vmsq_to_bus = m.vm[to_bus]**2
        elif coordinate_type == CoordinateType.RECTANGULAR:
            vmsq_from_bus = m.vr[from_bus]**2 + m.vj[from_bus]**2
            vmsq_to_bus = m.vr[to_bus]**2 + m.vj[to_bus]**2

        g = tx_calc.calculate_conductance(branch)
        b = tx_calc.calculate_susceptance(branch)
        bc = branch['charging_susceptance']
        tau = 1.0
        shift = 0.0

        if branch['branch_type'] == 'transformer':
            tau = branch['transformer_tap_ratio']
            shift = math.radians(branch['transformer_phase_shift'])

        g11 = g / tau**2
        g12 = g * math.cos(shift) / tau
        g21 = g * math.sin(shift) / tau
        g22 = g

        b11 = (b + bc / 2) / tau**2
        b12 = b * math.cos(shift) / tau
        b21 = b * math.sin(shift) / tau
        b22 = b + bc / 2

        m.eq_pf_branch[branch_name] = \
            m.pf[branch_name] == \
            g11 * vmsq_from_bus - \
            (g12 * m.c[(from_bus,to_bus)] +
             g21 * m.s[(from_bus,to_bus)] +
             b12 * m.s[(from_bus,to_bus)] -
             b21 * m.c[(from_bus,to_bus)])

        m.eq_pt_branch[branch_name] = \
            m.pt[branch_name] == \
            g22 * vmsq_to_bus - \
            (g12 * m.c[(from_bus,to_bus)] +
             g21 * m.s[(from_bus,to_bus)] -
             b12 * m.s[(from_bus,to_bus)] +
             b21 * m.c[(from_bus,to_bus)])

        m.eq_qf_branch[branch_name] = \
            m.qf[branch_name] == \
            -b11 * vmsq_from_bus + \
            (b12 * m.c[(from_bus,to_bus)] +
             b21 * m.s[(from_bus,to_bus)] -
             g12 * m.s[(from_bus,to_bus)] +
             g21 * m.c[(from_bus,to_bus)])

        m.eq_qt_branch[branch_name] = \
            m.qt[branch_name] == \
            -b22 * vmsq_to_bus + \
            (b12 * m.c[(from_bus,to_bus)] +
             b21 * m.s[(from_bus,to_bus)] +
             g12 * m.s[(from_bus,to_bus)] -
             g21 * m.c[(from_bus,to_bus)])
예제 #12
0
def declare_eq_branch_current(model,
                              index_set,
                              branches,
                              coordinate_type=CoordinateType.RECTANGULAR):
    """
    Create the equality constraints for the real and imaginary current
    in the branch
    """
    assert (coordinate_type != CoordinateType.POLAR
            and "Branch current in polar coordinates not implemented.")

    m = model
    con_set = decl.declare_set("_con_eq_branch_current_set", model, index_set)

    m.eq_ifr_branch = pe.Constraint(con_set)
    m.eq_ifj_branch = pe.Constraint(con_set)
    m.eq_itr_branch = pe.Constraint(con_set)
    m.eq_itj_branch = pe.Constraint(con_set)
    for branch_name in con_set:
        branch = branches[branch_name]
        if not branch['in_service']:
            continue

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

        g = tx_calc.calculate_conductance(branch)
        b = tx_calc.calculate_susceptance(branch)
        bc = branch['charging_susceptance']
        tau = 1.0
        shift = 0.0

        if branch['branch_type'] == 'transformer':
            tau = branch['transformer_tap_ratio']
            shift = math.radians(branch['transformer_phase_shift'])

        g11 = g / tau**2
        g12 = (g * math.cos(shift) - b * math.sin(shift)) / tau
        g21 = (g * math.cos(shift) + b * math.sin(shift)) / tau
        g22 = g

        b11 = (b + bc / 2) / tau**2
        b12 = (b * math.cos(shift) + g * math.sin(shift)) / tau
        b21 = (b * math.cos(shift) - g * math.sin(shift)) / tau
        b22 = b + bc / 2

        m.eq_ifr_branch[branch_name] = \
            m.ifr[branch_name] == \
            g11 * m.vr[from_bus] - g12 * m.vr[to_bus] - (b11 * m.vj[from_bus] - b12 * m.vj[to_bus])

        m.eq_ifj_branch[branch_name] = \
            m.ifj[branch_name] == \
            g11 * m.vj[from_bus] - g12 * m.vj[to_bus] + (b11 * m.vr[from_bus] - b12 * m.vr[to_bus])

        m.eq_itr_branch[branch_name] = \
            m.itr[branch_name] == \
            -(g21 * m.vr[from_bus] - g22 * m.vr[to_bus] - (b21 * m.vj[from_bus] - b22 * m.vj[to_bus]))

        m.eq_itj_branch[branch_name] = \
            m.itj[branch_name] == \
            -(g21 * m.vj[from_bus] - g22 * m.vj[to_bus] + (b21 * m.vr[from_bus] - b22 * m.vr[to_bus]))
예제 #13
0
def create_cold_start_lpac_model(model_data,
                                 cosine_segment_count=20,
                                 lower_bound=-pi / 3,
                                 upper_bound=pi / 3,
                                 include_feasibility_slack=False,
                                 mode="uniform"):
    """
	The cold start LPAC model assumes that no target voltages are available and that all voltages are initially approximated as 1 pu. 
	"""
    ###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 the polar voltages
    libbus.declare_var_va(model,
                          bus_attrs['names'],
                          initialize=bus_attrs['va'])

    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 voltage change variables
    decl.declare_var('phi', model, bus_attrs['names'])

    ### 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 (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()

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

    ### 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 at a bus (based on Kirchhoff Current Law)

    #Should be able to just use DC OPF approximation of B-theta type?

    ### declare the 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,
                                approximation_type=ApproximationType.BTHETA,
                                **p_rhs_kwargs)

    #Need one also for 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)

    ### Constraints for 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 - 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 - 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 - g*(model.va[from_bus] - model.va[to_bus]) + b*model.cos_hat[branch_name] - b*(model.phi[from_bus] - model.phi[to_bus])

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

### 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)

    ###Objective to match with acopf.py

    ### declare the generator cost objective
    libgen.declare_expression_pgqg_operating_cost(model=model,
                                                  index_set=gen_attrs['names'],
                                                  p_costs=gen_attrs['p_cost'],
                                                  q_costs=gen_attrs.get(
                                                      'q_cost', None))

    obj_expr = sum(model.pg_operating_cost[gen_name]
                   for gen_name in model.pg_operating_cost)
    if include_feasibility_slack:
        obj_expr += penalty_expr
    if hasattr(model, 'qg_operating_cost'):
        obj_expr += sum(model.qg_operating_cost[gen_name]
                        for gen_name in model.qg_operating_cost)

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

    return model, md
예제 #14
0
파일: bus.py 프로젝트: zkilwein/Egret
def declare_eq_p_balance_dc_approx(model,
                                   index_set,
                                   bus_p_loads,
                                   gens_by_bus,
                                   bus_gs_fixed_shunts,
                                   inlet_branches_by_bus,
                                   outlet_branches_by_bus,
                                   approximation_type=ApproximationType.BTHETA,
                                   **rhs_kwargs):
    """
    Create the equality constraints for the real power balance
    at a bus using the variables for real power flows, respectively.

    NOTE: Equation build orientates constants to the RHS in order to compute the correct dual variable sign
    """
    m = model
    con_set = decl.declare_set('_con_eq_p_balance', model, index_set)

    m.eq_p_balance = pe.Constraint(con_set)

    for bus_name in con_set:
        if approximation_type == ApproximationType.BTHETA:
            p_expr = -sum([
                m.pf[branch_name]
                for branch_name in outlet_branches_by_bus[bus_name]
            ])
            p_expr += sum([
                m.pf[branch_name]
                for branch_name in inlet_branches_by_bus[bus_name]
            ])
        elif approximation_type == ApproximationType.BTHETA_LOSSES:
            p_expr = -0.5 * sum([
                m.pfl[branch_name]
                for branch_name in inlet_branches_by_bus[bus_name]
            ])
            p_expr -= 0.5 * sum([
                m.pfl[branch_name]
                for branch_name in outlet_branches_by_bus[bus_name]
            ])
            p_expr -= sum([
                m.pf[branch_name]
                for branch_name in outlet_branches_by_bus[bus_name]
            ])
            p_expr += sum([
                m.pf[branch_name]
                for branch_name in inlet_branches_by_bus[bus_name]
            ])

        if bus_gs_fixed_shunts[bus_name] != 0.0:
            p_expr -= bus_gs_fixed_shunts[bus_name]

        if bus_p_loads[
                bus_name] != 0.0:  # only applies to fixed loads, otherwise may cause an error
            p_expr -= m.pl[bus_name]

        if rhs_kwargs:
            for idx, val in rhs_kwargs.items():
                if idx == 'include_feasibility_slack_pos':
                    p_expr -= eval("m." + val)[bus_name]
                if idx == 'include_feasibility_slack_neg':
                    p_expr += eval("m." + val)[bus_name]

        for gen_name in gens_by_bus[bus_name]:
            p_expr += m.pg[gen_name]

        m.eq_p_balance[bus_name] = \
            p_expr == 0.0
예제 #15
0
def declare_ineq_p_branch_thermal_lbub(
        model,
        index_set,
        branches,
        p_thermal_limits,
        approximation_type=ApproximationType.BTHETA,
        slacks=False):
    """
    Create the inequality constraints for the branch thermal limits
    based on the power variables or expressions.
    """
    m = model
    con_set = decl.declare_set('_con_ineq_p_branch_thermal_lbub',
                               model=model,
                               index_set=index_set)

    # flag for if slacks are on the model
    if slacks:
        if not hasattr(model, 'pf_slack_pos'):
            raise Exception(
                'No positive slack branch variables on model, but slacks=True')
        if not hasattr(model, 'pf_slack_neg'):
            raise Exception(
                'No negative slack branch variables on model, but slacks=True')

    m.ineq_pf_branch_thermal_lb = pe.Constraint(con_set)
    m.ineq_pf_branch_thermal_ub = pe.Constraint(con_set)

    if approximation_type == ApproximationType.BTHETA or \
            approximation_type == ApproximationType.PTDF:
        for branch_name in con_set:
            if p_thermal_limits[branch_name] is None:
                continue

            if slacks and branch_name in m.pf_slack_neg:
                pf_bn = m.pf[branch_name]
                if hasattr(pf_bn, 'expr') and isinstance(
                        pf_bn.expr, LinearExpression):
                    ## create a copy
                    old_expr = pf_bn.expr
                    expr = LinearExpression(
                        constant=old_expr.constant,
                        linear_vars=old_expr.linear_vars[:] +
                        [m.pf_slack_neg[branch_name]],
                        linear_coefs=old_expr.linear_coefs[:] + [1],
                    )

                else:
                    expr = m.pf[branch_name] + m.pf_slack_neg[branch_name]
                m.ineq_pf_branch_thermal_lb[branch_name] = \
                    (-p_thermal_limits[branch_name], expr, None)
            else:
                m.ineq_pf_branch_thermal_lb[branch_name] = \
                    (-p_thermal_limits[branch_name], m.pf[branch_name], None)

            if slacks and branch_name in m.pf_slack_pos:
                pf_bn = m.pf[branch_name]
                if hasattr(pf_bn, 'expr') and isinstance(
                        pf_bn.expr, LinearExpression):
                    ## create a copy
                    old_expr = pf_bn.expr
                    expr = LinearExpression(
                        constant=old_expr.constant,
                        linear_vars=old_expr.linear_vars[:] +
                        [m.pf_slack_pos[branch_name]],
                        linear_coefs=old_expr.linear_coefs[:] + [-1],
                    )
                else:
                    expr = m.pf[branch_name] - m.pf_slack_pos[branch_name]
                m.ineq_pf_branch_thermal_lb[branch_name] = \
                    (None, expr, p_thermal_limits[branch_name])
            else:
                m.ineq_pf_branch_thermal_ub[branch_name] = \
                    (None, m.pf[branch_name], p_thermal_limits[branch_name])
예제 #16
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
예제 #17
0
def _create_base_ac_with_pwl_approx_model(model_data, branch_dict, Q, include_feasibility_slack=False):
    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)

    bus_pairs = zip_items(branch_attrs['from_bus'], branch_attrs['to_bus'])
    unique_bus_pairs = list(OrderedDict((val, None) for idx, val in bus_pairs.items()))

    model = pe.ConcreteModel()

    ### 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()

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

    libbus.declare_var_vm(model=model, index_set=bus_attrs['names'], initialize=bus_attrs['vm'], bounds=zip_items(bus_attrs['v_min'], bus_attrs['v_max']))

    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()}))
    # libbranch.declare_var_c(model=model, index_set=unique_bus_pairs)
    # libbranch.declare_var_s(model=model, index_set=unique_bus_pairs)

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

    ###declare the phase angle differences in each branch
    libbranch.declare_var_dva(model, index_set=unique_bus_pairs)

    libbranch.declare_eq_delta_va(model, index_set=unique_bus_pairs)

    ### 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
                             )

    ### declare the branch power flow constraints



    ### declare a binary on/off variable for deenergizing a given branch

    decl.declare_var('u', model=model, index_set=branch_attrs['names'], within=pe.Binary)

    model.u.fix(1)

    branch_name_set = decl.declare_set('branch_name', model=model, index_set=branch_attrs['names'])

    model.box_index_set = pe.RangeSet(Q)

    model.power_type_set = pe.Set(initialize=[0,1])
    #Note: 0 is for power_type == "Active"; 1 is for power_type=="Reactive"

    #For active power energization/deenergization
    model.u_branch = pe.Var(branch_name_set, model.box_index_set, model.power_type_set, within=pe.Binary)

    #For selecting the appropriate interval of the PWL approximation
    model.dva_branch = pe.Var(branch_name_set, model.box_index_set, model.power_type_set)

    #(5) - Constraints for the on/off variable u

    def u_sum_rule(model, branch_name, j):
    	return model.u[branch_name] == sum(model.u_branch[branch_name, i, j] for i in model.box_index_set)

    model.u_sum_Constr = pe.Constraint(branch_name_set, model.power_type_set, rule=u_sum_rule)


    #(6) - Constraints that sum of dva variables should be equal to total dva

    #Upper bound constraints

    def delta_branch_ub_rule(model, branch_name, j):
    	branch = branches[branch_name]

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

    	return -model.dva[(from_bus, to_bus)] + sum(model.dva_branch[branch_name, i, j] for i in model.box_index_set) <= math.pi*(1-model.u[branch_name])

    model.delta_branch_ub_Constr = pe.Constraint(branch_name_set, model.power_type_set, rule=delta_branch_ub_rule)

    #Lower bound constraints

    def delta_branch_lb_rule(model, branch_name, j):
    	branch = branches[branch_name]

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

    	return -model.dva[(from_bus, to_bus)] + sum(model.dva_branch[branch_name, i, j] for i in model.box_index_set) >= -math.pi*(1-model.u[branch_name])

    model.delta_branch_lb_Constr = pe.Constraint(branch_name_set, model.power_type_set, rule=delta_branch_lb_rule)

    #(7) - Constraints that force dva variable to be in only one interval

    #Upper bound

    def delta_branch_box_ub_rule(model, branch_name, i, j):
    	if j==0:
    		delta_ub = branch_dict["Active_from_bus"][branch_name]['boxes']['coords'][i-1][7][2]
    	else:
    		delta_ub = branch_dict["Reactive_from_bus"][branch_name]['boxes']['coords'][i-1][7][2]
    	return model.dva_branch[branch_name, i, j] <= delta_ub*model.u_branch[branch_name, i, j]

    model.delta_branch_box_ub_Constr = pe.Constraint(branch_name_set, model.box_index_set, model.power_type_set, rule=delta_branch_box_ub_rule)

    def delta_branch_box_lb_rule(model, branch_name, i, j):
    	if j==0:
    		delta_lb = branch_dict["Active_from_bus"][branch_name]['boxes']['coords'][i-1][0][2]
    	else:
    		delta_lb = branch_dict["Reactive_from_bus"][branch_name]['boxes']['coords'][i-1][0][2]
    	return model.dva_branch[branch_name, i, j] >= delta_lb*model.u_branch[branch_name, i, j]

    model.delta_branch_box_lb_Constr = pe.Constraint(branch_name_set, model.box_index_set, model.power_type_set, rule=delta_branch_box_lb_rule)

    #(8) - Approximating power flow equation by PWL approximation



    #Active_from_bus
    def pwl_active_from_ub_rule(model, branch_name, i):
    	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)
    	coeffs = branch_dict["Active_from_bus"][branch_name]['boxes']['coefficients'][i-1]
    	#M = 10*(g+b) + 4*(coeffs[0]+coeffs[1]+coeffs[2]+coeffs[3])
    	M = 2*s_max[branch_name] + 10*(np.abs(coeffs[0])+np.abs(coeffs[1])+np.abs(coeffs[2])+np.abs(coeffs[3]))
    	return -model.pf[branch_name] + coeffs[0]*model.vm[from_bus] + coeffs[1]*model.vm[to_bus] + coeffs[2]*model.dva_branch[branch_name, i, 0] + coeffs[3] <= M*(1-model.u_branch[branch_name, i, 0])

    model.pwl_active_from_ub_Constr = pe.Constraint(branch_name_set, model.box_index_set, rule=pwl_active_from_ub_rule)

    def pwl_active_from_lb_rule(model, branch_name, i):
    	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)

    	coeffs = branch_dict["Active_from_bus"][branch_name]['boxes']['coefficients'][i-1]
    	#M = -(10*(g+b) + 4*(coeffs[0]+coeffs[1]+coeffs[2]+coeffs[3]))
    	M = -2*s_max[branch_name] - 10*(np.abs(coeffs[0])+np.abs(coeffs[1])+np.abs(coeffs[2])+np.abs(coeffs[3]))
    	return -model.pf[branch_name] + coeffs[0]*model.vm[from_bus] + coeffs[1]*model.vm[to_bus] + coeffs[2]*model.dva_branch[branch_name, i, 0] + coeffs[3] >= M*(1-model.u_branch[branch_name, i, 0])

    model.pwl_active_from_lb_Constr = pe.Constraint(branch_name_set, model.box_index_set, rule=pwl_active_from_lb_rule)

    #Active_to_bus
    def pwl_active_to_ub_rule(model, branch_name, i):
    	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)

    	coeffs = branch_dict["Active_to_bus"][branch_name]['boxes']['coefficients'][i-1]
    	#M = 10*(g+b) + 4*(coeffs[0]+coeffs[1]+coeffs[2]+coeffs[3])
    	M = 2*s_max[branch_name] + 10*(np.abs(coeffs[0])+np.abs(coeffs[1])+np.abs(coeffs[2])+np.abs(coeffs[3]))
    	return -model.pt[branch_name] + coeffs[0]*model.vm[from_bus] + coeffs[1]*model.vm[to_bus] + coeffs[2]*model.dva_branch[branch_name, i, 0] + coeffs[3] <= M*(1-model.u_branch[branch_name, i, 0])

    model.pwl_active_to_ub_Constr = pe.Constraint(branch_name_set, model.box_index_set, rule=pwl_active_to_ub_rule)

    def pwl_active_to_lb_rule(model, branch_name, i):
    	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)

    	coeffs = branch_dict["Active_to_bus"][branch_name]['boxes']['coefficients'][i-1]
    	#M = -(10*(g+b) + 4*(coeffs[0]+coeffs[1]+coeffs[2]+coeffs[3]))
    	M = -2*s_max[branch_name] - 10*(np.abs(coeffs[0])+np.abs(coeffs[1])+np.abs(coeffs[2])+np.abs(coeffs[3]))
    	return -model.pt[branch_name] + coeffs[0]*model.vm[from_bus] + coeffs[1]*model.vm[to_bus] + coeffs[2]*model.dva_branch[branch_name, i, 0] + coeffs[3] >= M*(1-model.u_branch[branch_name, i, 0])

    model.pwl_active_to_lb_Constr = pe.Constraint(branch_name_set, model.box_index_set, rule=pwl_active_to_lb_rule)

    #Reactive_from_bus

    def pwl_reactive_from_ub_rule(model, branch_name, i):
    	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)

    	coeffs = branch_dict["Reactive_from_bus"][branch_name]['boxes']['coefficients'][i-1]
    	#M = 10*(g+b) + 4*(coeffs[0]+coeffs[1]+coeffs[2]+coeffs[3])
    	M = 2*s_max[branch_name] + 10*(np.abs(coeffs[0])+np.abs(coeffs[1])+np.abs(coeffs[2])+np.abs(coeffs[3]))
    	return -model.qf[branch_name] + coeffs[0]*model.vm[from_bus] + coeffs[1]*model.vm[to_bus] + coeffs[2]*model.dva_branch[branch_name, i, 1] + coeffs[3] <= M*(1-model.u_branch[branch_name, i, 1])

    model.pwl_reactive_from_ub_Constr = pe.Constraint(branch_name_set, model.box_index_set, rule=pwl_reactive_from_ub_rule)

    def pwl_reactive_from_lb_rule(model, branch_name, i):
    	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)

    	coeffs = branch_dict["Reactive_from_bus"][branch_name]['boxes']['coefficients'][i-1]
    	#M = -(10*(g+b) + 4*(coeffs[0]+coeffs[1]+coeffs[2]+coeffs[3]))
    	M = -2*s_max[branch_name] - 10*(np.abs(coeffs[0])+np.abs(coeffs[1])+np.abs(coeffs[2])+np.abs(coeffs[3]))
    	return -model.qf[branch_name] + coeffs[0]*model.vm[from_bus] + coeffs[1]*model.vm[to_bus] + coeffs[2]*model.dva_branch[branch_name, i, 1] + coeffs[3] >= M*(1-model.u_branch[branch_name, i, 1])

    model.pwl_reactive_from_lb_Constr = pe.Constraint(branch_name_set, model.box_index_set, rule=pwl_reactive_from_lb_rule)

    #Reactive_to_bus

    def pwl_reactive_to_ub_rule(model, branch_name, i):
    	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)

    	coeffs = branch_dict["Reactive_to_bus"][branch_name]['boxes']['coefficients'][i-1]
    	#M = 10*(g+b) + 4*(coeffs[0]+coeffs[1]+coeffs[2]+coeffs[3])
    	M = 2*s_max[branch_name] + 10*(np.abs(coeffs[0])+np.abs(coeffs[1])+np.abs(coeffs[2])+np.abs(coeffs[3]))
    	return -model.qt[branch_name] + coeffs[0]*model.vm[from_bus] + coeffs[1]*model.vm[to_bus] + coeffs[2]*model.dva_branch[branch_name, i, 1] + coeffs[3] <= M*(1-model.u_branch[branch_name, i, 1])

    model.pwl_reactive_to_ub_Constr = pe.Constraint(branch_name_set, model.box_index_set, rule=pwl_reactive_to_ub_rule)

    def pwl_reactive_to_lb_rule(model, branch_name, i):
    	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)

    	coeffs = branch_dict["Reactive_to_bus"][branch_name]['boxes']['coefficients'][i-1]
    	#M = -(10*(g+b) + 4*(coeffs[0]+coeffs[1]+coeffs[2]+coeffs[3]))
    	M = -2*s_max[branch_name] - 10*(np.abs(coeffs[0])+np.abs(coeffs[1])+np.abs(coeffs[2])+np.abs(coeffs[3]))
    	return -model.qt[branch_name] + coeffs[0]*model.vm[from_bus] + coeffs[1]*model.vm[to_bus] + coeffs[2]*model.dva_branch[branch_name, i, 1] + coeffs[3] >= M*(1-model.u_branch[branch_name, i, 1])

    model.pwl_reactive_to_lb_Constr = pe.Constraint(branch_name_set, model.box_index_set, rule=pwl_reactive_to_lb_rule)

    
    ### declare the pq balances
    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
                                )

    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
                                )

    ### declare the thermal limits
    libbranch.declare_ineq_s_branch_thermal_limit(model=model,
                                                  index_set=branch_attrs['names'],
                                                  branches=branches,
                                                  s_thermal_limits=s_max,
                                                  flow_type=FlowType.POWER
                                                  )

    # declare angle difference limits on interconnected buses
    # libbranch.declare_ineq_angle_diff_branch_lbub_c_s(model=model,
    #                                                   index_set=branch_attrs['names'],
    #                                                   branches=branches
    #                                                   )

    ### declare the generator cost objective
    libgen.declare_expression_pgqg_operating_cost(model=model,
                                                  index_set=gen_attrs['names'],
                                                  p_costs=gen_attrs['p_cost'],
                                                  q_costs=gen_attrs.get('q_cost', None)
                                                  )

    obj_expr = sum(model.pg_operating_cost[gen_name] for gen_name in model.pg_operating_cost)
    if include_feasibility_slack:
        obj_expr += penalty_expr
    if hasattr(model, 'qg_operating_cost'):
        obj_expr += sum(model.qg_operating_cost[gen_name] for gen_name in model.qg_operating_cost)

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

    return model, md