def create_ptdf_losses_dcopf_model(model_data, include_feasibility_slack=False, ptdf_options=None): ptdf_options = lpu.populate_default_ptdf_options(ptdf_options) baseMVA = model_data.data['system']['baseMVA'] lpu.check_and_scale_ptdf_options(ptdf_options, baseMVA) 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') load_attrs = md.attributes(element_type='load') shunt_attrs = md.attributes(element_type='shunt') 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 loads at the buses bus_p_loads, _ = tx_utils.dict_of_bus_loads(buses, loads) libbus.declare_var_pl(model, bus_attrs['names'], initialize=bus_p_loads) model.pl.fix() ### declare the fixed shunts at the buses _, bus_gs_fixed_shunts = tx_utils.dict_of_bus_fixed_shunts(buses, shunts) ### 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(model, gen_attrs['names'], initialize=pg_init, bounds=zip_items(gen_attrs['p_min'], gen_attrs['p_max']) ) ### include the feasibility slack for the system balance p_rhs_kwargs = {} if include_feasibility_slack: p_rhs_kwargs, penalty_expr = _include_system_feasibility_slack(model, gen_attrs, bus_p_loads) ### declare net withdraw expression for use in PTDF power flows libbus.declare_expr_p_net_withdraw_at_bus(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, ) ### declare the current flows in the branches p_max = {k: branches[k]['rating_long_term'] for k in branches.keys()} pfl_bounds = {k: (-p_max[k]**2,p_max[k]**2) for k in branches.keys()} pfl_init = {k: 0 for k in branches.keys()} ## Do and store PTDF calculation reference_bus = md.data['system']['reference_bus'] ## We'll assume we have a solution to initialize from base_point = BasePointType.SOLUTION PTDF = ptdf_utils.PTDFLossesMatrix(branches, buses, reference_bus, base_point, ptdf_options) model._PTDF = PTDF model._ptdf_options = ptdf_options libbranch.declare_expr_pf(model=model, index_set=branch_attrs['names'], ) libbranch.declare_var_pfl(model=model, index_set=branch_attrs['names'], initialize=pfl_init, bounds=pfl_bounds ) ### declare the branch power flow approximation constraints libbranch.declare_eq_branch_power_ptdf_approx(model=model, index_set=branch_attrs['names'], PTDF=PTDF, abs_ptdf_tol=ptdf_options['abs_ptdf_tol'], rel_ptdf_tol=ptdf_options['rel_ptdf_tol'], ) ### declare the branch power loss approximation constraints libbranch.declare_eq_branch_loss_ptdf_approx(model=model, index_set=branch_attrs['names'], PTDF=PTDF, abs_ptdf_tol=ptdf_options['abs_ptdf_tol'], rel_ptdf_tol=ptdf_options['rel_ptdf_tol'], ) ### declare the p balance libbus.declare_eq_p_balance_ed(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, include_losses=branch_attrs['names'], **p_rhs_kwargs ) ### declare the real power flow limits libbranch.declare_ineq_p_branch_thermal_lbub(model=model, index_set=branch_attrs['names'], branches=branches, p_thermal_limits=p_max, approximation_type=ApproximationType.PTDF ) ### declare the generator cost objective libgen.declare_expression_pgqg_operating_cost(model=model, index_set=gen_attrs['names'], p_costs=gen_attrs['p_cost'] ) 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 model.obj = pe.Objective(expr=obj_expr) return model, md
def create_btheta_losses_dcopf_model(model_data, relaxation_type=RelaxationType.SOC, include_angle_diff_limits=False, 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') load_attrs = md.attributes(element_type='load') shunt_attrs = md.attributes(element_type='shunt') 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 loads at the buses bus_p_loads, _ = tx_utils.dict_of_bus_loads(buses, loads) libbus.declare_var_pl(model, bus_attrs['names'], initialize=bus_p_loads) model.pl.fix() ### 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']} libbus.declare_var_va(model, bus_attrs['names'], initialize=bus_attrs['va'], bounds=va_bounds ) dva_initialize = {k: 0.0 for k in branch_attrs['names']} libbranch.declare_var_dva(model, branch_attrs['names'], initialize=dva_initialize ) ### include the feasibility slack for the bus balances p_rhs_kwargs = {} penalty_expr = None if include_feasibility_slack: p_rhs_kwargs, penalty_expr = _include_feasibility_slack(model, bus_attrs, gen_attrs, bus_p_loads) ### 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(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(model, gen_attrs['names'], initialize=pg_init, bounds=zip_items(gen_attrs['p_min'], gen_attrs['p_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']} p_max = {k: branches[k]['rating_long_term'] for k in branches.keys()} pf_bounds = {k: (-p_max[k],p_max[k]) for k in branches.keys()} 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]) pfl_bounds = {k: (0,p_max[k]**2) for k in branches.keys()} pfl_init = {k: 0 for k in branches.keys()} libbranch.declare_var_pf(model=model, index_set=branch_attrs['names'], initialize=pf_init, bounds=pf_bounds ) libbranch.declare_var_pfl(model=model, index_set=branch_attrs['names'], initialize=pfl_init, bounds=pfl_bounds ) ### declare the angle difference constraint libbranch.declare_eq_branch_dva(model=model, index_set=branch_attrs['names'], branches=branches ) ### declare the branch power flow approximation constraints libbranch.declare_eq_branch_power_btheta_approx(model=model, index_set=branch_attrs['names'], branches=branches, approximation_type=ApproximationType.BTHETA_LOSSES ) ### declare the branch power loss approximation constraints libbranch.declare_eq_branch_loss_btheta_approx(model=model, index_set=branch_attrs['names'], branches=branches, relaxation_type=relaxation_type ) ### declare the p balance libbus.declare_eq_p_balance_dc_approx(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_LOSSES, **p_rhs_kwargs ) ### declare the real power flow limits libbranch.declare_ineq_p_branch_thermal_lbub(model=model, index_set=branch_attrs['names'], branches=branches, p_thermal_limits=p_max, approximation_type=ApproximationType.BTHETA ) ### declare angle difference limits on interconnected buses if include_angle_diff_limits: libbranch.declare_ineq_angle_diff_branch_lbub(model=model, index_set=branch_attrs['names'], branches=branches, coordinate_type=CoordinateType.POLAR ) ### declare the generator cost objective libgen.declare_expression_pgqg_operating_cost(model=model, index_set=gen_attrs['names'], p_costs=gen_attrs['p_cost'] ) 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 model.obj = pe.Objective(expr=obj_expr) return model, md
def create_ptdf_losses_dcopf_model(model_data, include_feasibility_slack=False): md = model_data.clone_in_service() tx_utils.scale_ModelData_to_pu(md, inplace=True) data_utils.create_dicts_of_ptdf_losses(md) 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') load_attrs = md.attributes(element_type='load') shunt_attrs = md.attributes(element_type='shunt') 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 loads at the buses bus_p_loads, _ = tx_utils.dict_of_bus_loads(buses, loads) libbus.declare_var_pl(model, bus_attrs['names'], initialize=bus_p_loads) model.pl.fix() ### declare the fixed shunts at the buses _, bus_gs_fixed_shunts = tx_utils.dict_of_bus_fixed_shunts(buses, shunts) ### 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(model, gen_attrs['names'], initialize=pg_init, bounds=zip_items(gen_attrs['p_min'], gen_attrs['p_max'])) ### include the feasibility slack for the system balance p_rhs_kwargs = {} if include_feasibility_slack: p_rhs_kwargs, penalty_expr = _include_system_feasibility_slack( model, gen_attrs, bus_p_loads) ### 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'] } p_max = {k: branches[k]['rating_long_term'] for k in branches.keys()} pf_bounds = {k: (-p_max[k], p_max[k]) for k in branches.keys()} 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]) pfl_bounds = {k: (-p_max[k]**2, p_max[k]**2) for k in branches.keys()} pfl_init = {k: 0 for k in branches.keys()} libbranch.declare_var_pf(model=model, index_set=branch_attrs['names'], initialize=pf_init, bounds=pf_bounds) libbranch.declare_var_pfl(model=model, index_set=branch_attrs['names'], initialize=pfl_init, bounds=pfl_bounds) ### declare the branch power flow approximation constraints libbranch.declare_eq_branch_power_ptdf_approx( model=model, index_set=branch_attrs['names'], branches=branches, buses=buses, bus_p_loads=bus_p_loads, gens_by_bus=gens_by_bus, bus_gs_fixed_shunts=bus_gs_fixed_shunts, approximation_type=ApproximationType.PTDF_LOSSES) ### declare the branch power loss approximation constraints libbranch.declare_eq_branch_loss_ptdf_approx( model=model, index_set=branch_attrs['names'], branches=branches, buses=buses, bus_p_loads=bus_p_loads, gens_by_bus=gens_by_bus, bus_gs_fixed_shunts=bus_gs_fixed_shunts) ### declare the p balance libbus.declare_eq_p_balance_ed(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, include_losses=branch_attrs['names'], **p_rhs_kwargs) ### declare the real power flow limits libbranch.declare_ineq_p_branch_thermal_lbub( model=model, index_set=branch_attrs['names'], branches=branches, p_thermal_limits=p_max, approximation_type=ApproximationType.PTDF) ### declare the generator cost objective libgen.declare_expression_pgqg_operating_cost(model=model, index_set=gen_attrs['names'], p_costs=gen_attrs['p_cost']) 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 model.obj = pe.Objective(expr=obj_expr) return model, md