Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding user-configurable slack type #239

Merged
merged 6 commits into from
Aug 17, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
initial switch
  • Loading branch information
bknueven committed Jun 25, 2021
commit f6d3e3b205b530341e196f233f06bc0ef6d7428b
2 changes: 1 addition & 1 deletion egret/common/lazy_ptdf_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,7 @@ def _add_contingency_violations(lazy_violations, flows, mb, md, solver, ptdf_opt
contingencies_monitored.append((cn, i_b))
if new_slacks:
m = model
obj_coef = pyo.value(m.TimePeriodLengthHours*m.ContingencyLimitPenalty)
obj_coef = pyo.value(m.TimePeriodLengthHours*m.SystemContingencyLimitPenalty)

if persistent_solver:
m_model = m.model()
Expand Down
2 changes: 1 addition & 1 deletion egret/model_library/transmission/branch.py
Original file line number Diff line number Diff line change
Expand Up @@ -1090,7 +1090,7 @@ def declare_ineq_p_contingency_branch_thermal_bounds(model, index_set,
pos_slack = m.pfc_slack_pos[contingency_name, branch_name]
uc_model = slack_cost_expr.parent_block()
slack_cost_expr.expr += (uc_model.TimePeriodLengthHours
* uc_model.ContingencyLimitPenalty
* uc_model.SystemContingencyLimitPenalty
* (neg_slack + pos_slack) )
assert len(m.pfc_slack_pos) == len(m.pfc_slack_neg)
else:
Expand Down
73 changes: 49 additions & 24 deletions egret/model_library/unit_commitment/params.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,34 @@ def load_params(model, model_data):
initialize={'Stage_1':model.TimePeriods, 'Stage_2': list() } )
model.GenerationTimeInStage = Set(model.StageSet, within=model.TimePeriods,
initialize={'Stage_1': list(), 'Stage_2': model.TimePeriods } )

##########################################
# penalty costs for constraint violation #
##########################################

ModeratelyBigPenalty = 1e3*system['baseMVA']

model.ReserveShortfallPenalty = Param(within=NonNegativeReals, default=ModeratelyBigPenalty, mutable=True, initialize=system.get('reserve_shortfall_cost', ModeratelyBigPenalty))

BigPenalty = 1e4*system['baseMVA']

model.LoadMismatchPenalty = Param(within=NonNegativeReals, mutable=True, initialize=system.get('load_mismatch_cost', BigPenalty))
model.LoadMismatchPenaltyReactive = Param(within=NonNegativeReals, mutable=True, initialize=system.get('q_load_mismatch_cost', BigPenalty/2.))

model.Contingencies = Set(initialize=contingencies.keys())

# leaving this unindexed for now for simpility
model.SystemContingencyLimitPenalty = Param(within=NonNegativeReals,
initialize=system.get('contingency_flow_violation_cost', BigPenalty/2.),
mutable=True)

model.SystemTransmissionLimitPenalty = Param(within=NonNegativeReals,
initialize=system.get('transmission_flow_violation_cost', BigPenalty/2.),
mutable=True)

model.SystemInterfaceLimitPenalty = Param(within=NonNegativeReals,
initialize=system.get('interface_flow_violation_cost', BigPenalty/4.),
mutable=True)

##############################################
# Network definition (S)
Expand Down Expand Up @@ -230,18 +258,25 @@ def _warn_neg_impedence(m, v, l):
model.HVDCLineOutOfService = Param(model.HVDCLines, model.TimePeriods, within=Boolean, default=False,
initialize=TimeMapper(dc_branch_attrs.get('planned_outage', dict())))

_branch_penalties = dict()
_md_violation_penalties = branch_attrs.get('violation_penalty')
_branch_penalties = {}
_branches_without_slack = set()
if _md_violation_penalties is not None:
for i, val in _md_violation_penalties.items():
if val is not None:
if val is None:
_branches_without_slack.add(i)
else:
_branch_penalties[i] = val
if val <= 0:
logger.warning("Branch {} has a non-positive penalty {}, this will cause its limits to be ignored!".format(i,val))

model.BranchesWithSlack = Set(within=model.TransmissionLines, initialize=_branch_penalties.keys())
model.BranchesWithSlack = Set(within=model.TransmissionLines, initialize=(set(model.TransmissionLines) - _branches_without_slack))

model.BranchLimitPenalty = Param(model.BranchesWithSlack, within=NonNegativeReals, initialize=_branch_penalties)
model.BranchLimitPenalty = Param(model.BranchesWithSlack,
within=NonNegativeReals,
default=value(model.SystemTransmissionLimitPenalty),
mutable=True,
initialize=_branch_penalties)

## Interfaces
model.Interfaces = Set(initialize=interface_attrs['names'])
Expand Down Expand Up @@ -270,18 +305,25 @@ def get_interface_line_pairs(m):

model.InterfaceLineOrientation = Param(model.InterfaceLinePairs, initialize=_interface_line_orientation_dict, within=set([-1,0,1]))

_interface_penalties = dict()
_md_violation_penalties = interface_attrs.get('violation_penalty')
_interface_penalties = dict()
_interfaces_without_slack = set()
if _md_violation_penalties is not None:
for i, val in _md_violation_penalties.items():
if val is not None:
_interfaces_without_slack.add(i)
else:
_interface_penalties[i] = val
if val <= 0:
logger.warning("Interface {} has a non-positive penalty {}, this will cause its limits to be ignored!".format(i,val))

model.InterfacesWithSlack = Set(within=model.Interfaces, initialize=_interface_penalties.keys())
model.InterfacesWithSlack = Set(within=model.Interfaces, initialize=(set(model.Interfaces) - _interfaces_without_slack))

model.InterfaceLimitPenalty = Param(model.InterfacesWithSlack, within=NonNegativeReals, initialize=_interface_penalties)
model.InterfaceLimitPenalty = Param(model.InterfacesWithSlack,
within=NonNegativeReals,
default=value(model.SystemInterfaceLimitPenalty),
mutable=True,
initialize=_interface_penalties)

##########################################################
# string indentifiers for the set of thermal generators. #
Expand Down Expand Up @@ -1257,23 +1299,6 @@ def power_generation_piecewise_points_rule(m, g):

## END PRODUCTION COST CALCULATIONS

#########################################
# penalty costs for constraint violation #
#########################################

ModeratelyBigPenalty = 1e3*system['baseMVA']

model.ReserveShortfallPenalty = Param(within=NonNegativeReals, default=ModeratelyBigPenalty, mutable=True, initialize=system.get('reserve_shortfall_cost', ModeratelyBigPenalty))

BigPenalty = 1e4*system['baseMVA']

model.LoadMismatchPenalty = Param(within=NonNegativeReals, mutable=True, initialize=system.get('load_mismatch_cost', BigPenalty))
model.LoadMismatchPenaltyReactive = Param(within=NonNegativeReals, mutable=True, initialize=system.get('q_load_mismatch_cost', BigPenalty/2.))

model.Contingencies = Set(initialize=contingencies.keys())

# leaving this unindexed for now for simpility
model.ContingencyLimitPenalty = Param(within=NonNegativeReals, initialize=system.get('contingency_flow_violation_cost', BigPenalty/2.), mutable=True)

#
# STORAGE parameters
Expand Down
49 changes: 29 additions & 20 deletions egret/model_library/unit_commitment/power_balance.py
Original file line number Diff line number Diff line change
Expand Up @@ -591,27 +591,29 @@ def qg_expr_rule(block,b):
return qg_expr_rule

## Defines generic interface for egret tramsmission models
def _add_egret_power_flow(model, network_model_builder, reactive_power=False, slacks=True):
def _add_egret_power_flow(model, network_model_builder,
reactive_power=False, slacks=True,
slacks_by_bus=False):

## save flag for objective
model.reactive_power = reactive_power

system_load_mismatch = (network_model_builder in \
if (network_model_builder in \
[_copperplate_approx_network_model, \
_copperplate_relax_network_model, \
]
)
):
# only one slack as there's only a
# single power-balance constraint
slacks_by_bus = False

if slacks:
if system_load_mismatch:
_add_system_load_mismatch(model)
else:
if slacks_by_bus:
_add_load_mismatch(model)
else:
if system_load_mismatch:
_add_blank_system_load_mismatch(model)
else:
_add_blank_load_mismatch(model)
_add_system_load_mismatch(model)
else:
_add_blank_load_mismatch(model)

_add_hvdc(model)

Expand Down Expand Up @@ -653,40 +655,44 @@ def _add_egret_power_flow(model, network_model_builder, reactive_power=False, sl
'non_dispatchable_vars': None,
'storage_service': None,
})
def copperplate_power_flow(model, slacks=True):
_add_egret_power_flow(model, _copperplate_approx_network_model, reactive_power=False, slacks=slacks)
def copperplate_power_flow(model, slacks=True, slacks_by_bus=False):
_add_egret_power_flow(model, _copperplate_approx_network_model, reactive_power=False,
slacks=slacks, slacks_by_bus=slacks_by_bus)

@add_model_attr(component_name, requires = {'data_loader': None,
'power_vars': None,
'non_dispatchable_vars': None,
'storage_service': None,
})
def copperplate_relaxed_power_flow(model, slacks=True):
_add_egret_power_flow(model, _copperplate_relax_network_model, reactive_power=False, slacks=slacks)
def copperplate_relaxed_power_flow(model, slacks=True, slacks_by_bus=False):
_add_egret_power_flow(model, _copperplate_relax_network_model, reactive_power=False,
slacks=slacks, slacks_by_bus=slacks_by_bus)

@add_model_attr(component_name, requires = {'data_loader': None,
'power_vars': None,
'non_dispatchable_vars': None,
'storage_service': None,
})
def ptdf_power_flow(model, slacks=True):
_add_egret_power_flow(model, _ptdf_dcopf_network_model, reactive_power=False, slacks=slacks)
def ptdf_power_flow(model, slacks=True, slacks_by_bus=False):
_add_egret_power_flow(model, _ptdf_dcopf_network_model, reactive_power=False,
slacks=slacks, slacks_by_bus=slacks_by_bus)

@add_model_attr(component_name, requires = {'data_loader': None,
'power_vars': None,
'non_dispatchable_vars': None,
'storage_service': None,
})
def btheta_power_flow(model, slacks=True):
_add_egret_power_flow(model, _btheta_dcopf_network_model, reactive_power=False, slacks=slacks)
def btheta_power_flow(model, slacks=True, slacks_by_bus=False):
_add_egret_power_flow(model, _btheta_dcopf_network_model, reactive_power=False,
slacks=slacks, slacks_by_bus=slacks_by_bus)


@add_model_attr(component_name, requires = {'data_loader': None,
'power_vars': None,
'non_dispatchable_vars': None,
'storage_service': None,
})
def power_balance_constraints(model, slacks=True):
def power_balance_constraints(model, slacks=True, slacks_by_bus=False):
'''
adds the demand and network constraints to the model
'''
Expand Down Expand Up @@ -769,7 +775,10 @@ def interface_violation_cost_rule(m,t):
model.ContingencyViolationCost = Expression(model.TimePeriods, rule=lambda m,t:0.)

if slacks:
_add_load_mismatch(model)
if slacks_by_bus:
_add_load_mismatch(model)
else:
_add_system_load_mismatch(model)
else:
_add_blank_load_mismatch(model)

Expand Down