Skip to content

Commit

Permalink
Merge pull request #235 from TAMUparametric/modes_fix
Browse files Browse the repository at this point in the history
Modes fix
  • Loading branch information
cacodcar committed Jun 15, 2024
2 parents 6df5339 + d3ea88a commit caf8a43
Show file tree
Hide file tree
Showing 9 changed files with 557 additions and 904 deletions.
7 changes: 4 additions & 3 deletions src/energiapy/components/case_study.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def formulate(self, constraints: Set[Constraints] = None, objective: Objective =

return self.formulations

def solve(self, solver: str, interface: str = 'pyomo', saveformat: str = None, print_solversteps: bool = True, log: bool = False) -> Dict[str, Result]:
def solve(self, solver: str, interface: str = 'pyomo', saveformat: str = None, print_solversteps: bool = True, log: bool = False, get_duals: bool = False) -> Dict[str, Result]:
"""solves all the instances in the case study
Args:
Expand All @@ -101,6 +101,7 @@ def solve(self, solver: str, interface: str = 'pyomo', saveformat: str = None, p
saveformat (str, optional): .pkl, .json, .txt. Defaults to None.
print_solversteps (bool, optional):. Defaults to True.
log (bool, optional): Log nearbounds in case of optimal, and violations if infeasible. Defaults to False
get_duals (bool, optional): get and save the duals in the results
Returns:
Result: result type object
Expand All @@ -113,7 +114,7 @@ def solve(self, solver: str, interface: str = 'pyomo', saveformat: str = None, p

self.results = Results(name=self.name + '_results', results={names[i]: solve_casestudy(instance=instances[i], scenario=self.scenarios[i],
solver=solver, name=names[
i], interface=interface, saveformat=saveformat,
print_solversteps=print_solversteps, log=log) for i in range(len(names))})
i], interface=interface, saveformat=saveformat,
print_solversteps=print_solversteps, log=log, get_duals=get_duals) for i in range(len(names))})

return self.results
194 changes: 68 additions & 126 deletions src/energiapy/model/constraints/cost.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ def constraint_process_capex(instance: ConcreteModel, capex_dict: dict, network_
instance (ConcreteModel): pyomo instance
capex_dict (dict): capex at location
network_scale_level (int, optional): scale of network decisions. Defaults to 0.
annualization_factor (float, optional): Annual depreciation of asset. Defaults to 1.
annualization_factor (float, optional): Annualization of capital investment. Defaults to 1.
Returns:
Constraint: process_capex
Expand All @@ -342,17 +342,6 @@ def constraint_process_capex(instance: ConcreteModel, capex_dict: dict, network_

def process_capex_rule(instance, location, process, *scale_list):

# if capex_dict[process] is not None:
# if capex_factor[location] is not None:
# if process in list(capex_factor[location].keys()):
# return instance.Capex_process[location, process, scale_list] == annualization_factor*capex_factor[location][process][scale_list]*capex_dict[process]*instance.Cap_P[location, process, scale_list]
# else:
# return instance.Capex_process[location, process, scale_list] == annualization_factor*capex_dict[process]*instance.Cap_P[location, process, scale_list]
# else:
# return instance.Capex_process[location, process, scale_list] == annualization_factor*capex_dict[process]*instance.Cap_P[location, process, scale_list]
# else:
# return instance.Capex_process[location, process, scale_list] == 0

if capex_dict[process] is not None:
Cap_P = instance.Cap_P[location, process, scale_list]
else:
Expand Down Expand Up @@ -419,43 +408,14 @@ def network_capex_rule(instance, *scale_list):
constraint_latex_render(network_capex_rule)
return instance.constraint_network_capex

# *-------------------------vopex costing constraints----------------------------


# def constraint_process_vopex(instance: ConcreteModel, vopex_dict: dict, network_scale_level: int = 0, vopex_factor: dict = None, location_process_dict: dict = None) -> Constraint:
# """Fixed operational expenditure for each process at location in network

# Args:
# instance (ConcreteModel): pyomo instance
# network_scale_level (int, optional): scale of network decisions. Defaults to 0.

# Returns:
# Constraint: process_vopex
# """
# scales = scale_list(instance=instance, scale_levels=network_scale_level+1)

# def process_vopex_rule(instance, location, process, *scale_list):
# if vopex_dict[process] is not None:
# if vopex_factor[location] is not None:
# return instance.Vopex_process[location, process, scale_list] == vopex_factor[location][process][scale_list]*vopex_dict[process]*instance.P_location[location, process, scale_list]
# else:
# return instance.Vopex_process[location, process, scale_list] == vopex_dict[process]*instance.P_location[location, process, scale_list]
# else:
# return instance.Vopex_process[location, process, scale_list] == 0
# instance.constraint_process_vopex = Constraint(
# instance.locations, instance.processes, *scales, rule=process_vopex_rule, doc='total vopex from network')
# constraint_latex_render(process_vopex_rule)
# return instance.constraint_process_vopex


def constraint_process_vopex(instance: ConcreteModel, vopex_dict: dict, network_scale_level: int = 0, annualization_factor: float = 1, vopex_factor: dict = None, cost_dynamics: Costdynamics = Costdynamics.constant, location_process_dict: dict = None) -> Constraint:
def constraint_process_vopex(instance: ConcreteModel, vopex_dict: dict, network_scale_level: int = 0, vopex_factor: dict = None, cost_dynamics: Costdynamics = Costdynamics.constant, location_process_dict: dict = None) -> Constraint:
"""Capital expenditure for each process at location in network
Args:
instance (ConcreteModel): pyomo instance
vopex_dict (dict): vopex at location
network_scale_level (int, optional): scale of network decisions. Defaults to 0.
annualization_factor (float, optional): Annual depreciation of asset. Defaults to 1.
Returns:
Constraint: process_vopex
Expand All @@ -478,12 +438,12 @@ def process_vopex_rule(instance, location, process, *scale_list):
vopex_fact = 1

if get_depth(vopex_dict) == 1:
return instance.Vopex_process[location, process, scale_list] == annualization_factor*vopex_fact*vopex_dict[process]*P_location
return instance.Vopex_process[location, process, scale_list] == vopex_fact*vopex_dict[process]*P_location
else:
if hasattr(instance, 'X_M') is True:
return instance.Vopex_process[location, process, scale_list] == sum(annualization_factor*vopex_fact*vopex_dict[i[0]][i[1]]*instance.P_location_material_m[location, i[0], i[1], scale_list] for i in instance.process_material_modes if i[0] == process)
return instance.Vopex_process[location, process, scale_list] == sum(vopex_fact*vopex_dict[i[0]][i[1]]*instance.P_location_material_m[location, i[0], i[1], scale_list] for i in instance.process_material_modes if i[0] == process)
if hasattr(instance, 'X_P_m') is True:
return instance.Vopex_process[location, process, scale_list] == sum(annualization_factor*vopex_fact*vopex_dict[i[0]][i[1]]*P_location for i in instance.process_material_modes if i[0] == process)
return instance.Vopex_process[location, process, scale_list] == sum(vopex_fact*vopex_dict[i[0]][i[1]]*P_location for i in instance.process_material_modes if i[0] == process)
instance.constraint_process_vopex = Constraint(
instance.locations, instance.processes, *scales, rule=process_vopex_rule, doc='vopex for process')

Expand Down Expand Up @@ -534,14 +494,13 @@ def network_vopex_rule(instance, *scale_list):
# *-------------------------fopex costing constraints----------------------------


def constraint_process_fopex(instance: ConcreteModel, fopex_dict: dict, network_scale_level: int = 0, annualization_factor: float = 1, fopex_factor: dict = None, cost_dynamics: Costdynamics = Costdynamics.constant, location_process_dict: dict = None) -> Constraint:
def constraint_process_fopex(instance: ConcreteModel, fopex_dict: dict, network_scale_level: int = 0, fopex_factor: dict = None, cost_dynamics: Costdynamics = Costdynamics.constant, location_process_dict: dict = None) -> Constraint:
"""Capital expenditure for each process at location in network
Args:
instance (ConcreteModel): pyomo instance
fopex_dict (dict): fopex at location
network_scale_level (int, optional): scale of network decisions. Defaults to 0.
annualization_factor (float, optional): Annual depreciation of asset. Defaults to 1.
Returns:
Constraint: process_fopex
Expand All @@ -564,44 +523,18 @@ def process_fopex_rule(instance, location, process, *scale_list):
fopex_fact = 1

if get_depth(fopex_dict) == 1:
return instance.Fopex_process[location, process, scale_list] == annualization_factor*fopex_fact*fopex_dict[process]*Cap_P
return instance.Fopex_process[location, process, scale_list] == fopex_fact*fopex_dict[process]*Cap_P
else:
if hasattr(instance, 'X_M') is True:
return instance.Fopex_process[location, process, scale_list] == sum(annualization_factor*fopex_fact*fopex_dict[i[0]][i[1]]*instance.Cap_P_M[location, i[0], i[1], scale_list] for i in instance.process_material_modes if i[0] == process)
return instance.Fopex_process[location, process, scale_list] == sum(fopex_fact*fopex_dict[i[0]][i[1]]*instance.Cap_P_M[location, i[0], i[1], scale_list] for i in instance.process_material_modes if i[0] == process)
if hasattr(instance, 'X_P_m') is True:
return instance.Fopex_process[location, process, scale_list] == sum(annualization_factor*fopex_fact*fopex_dict[i[0]][i[1]]*Cap_P for i in instance.process_material_modes if i[0] == process)
return instance.Fopex_process[location, process, scale_list] == sum(fopex_fact*fopex_dict[i[0]][i[1]]*Cap_P for i in instance.process_material_modes if i[0] == process)
instance.constraint_process_fopex = Constraint(
instance.locations, instance.processes, *scales, rule=process_fopex_rule, doc='fopex for process')

constraint_latex_render(process_fopex_rule)
return instance.constraint_process_fopex

# def constraint_process_fopex(instance: ConcreteModel, fopex_dict: dict, network_scale_level: int = 0, fopex_factor: dict = None, annualization_factor: float = 1, location_process_dict: dict = None) -> Constraint:
# """Fixed operational expenditure for each process at location in network
# Args:
# instance (ConcreteModel): pyomo instance
# fopex_dict (dict): fixed opex at location
# network_scale_level (int, optional): scale of network decisions. Defaults to 0.
# annualization_factor (float, optional): Annual depreciation of asset. Defaults to 1.

# Returns:
# Constraint: process_fopex
# """
# scales = scale_list(instance=instance, scale_levels=network_scale_level+1)

# def process_fopex_rule(instance, location, process, *scale_list):
# if fopex_dict[process] is not None:
# if fopex_factor[location] is not None:
# return instance.Fopex_process[location, process, scale_list] == annualization_factor*fopex_factor[location][process][scale_list]*fopex_dict[process]*instance.Cap_P[location, process, scale_list]
# else:
# return instance.Fopex_process[location, process, scale_list] == annualization_factor*fopex_dict[process]*instance.Cap_P[location, process, scale_list]
# else:
# return instance.Fopex_process[location, process, scale_list] == 0
# instance.constraint_process_fopex = Constraint(
# instance.locations, instance.processes, *scales, rule=process_fopex_rule, doc='fopex for process')
# constraint_latex_render(process_fopex_rule)
# return instance.constraint_process_fopex


def constraint_location_fopex(instance: ConcreteModel, network_scale_level: int = 0) -> Constraint:
"""Fixed operational expenditure for each process at location in network
Expand Down Expand Up @@ -786,56 +719,6 @@ def network_incidental_rule(instance, *scale_list):
constraint_latex_render(network_incidental_rule)
return instance.constraint_network_incidental

# *-------------------------Total network cost--------------------------


def constraint_network_cost(instance: ConcreteModel, constraints=Set[Constraints], network_scale_level: int = 0) -> Constraint:
"""Total network costs
Args:
instance (ConcreteModel): pyomo instance
network_scale_level (int, optional): scale of network decisions. Defaults to 0.
Returns:
Constraint: total network cost
"""
scale_iter = scale_tuple(
instance=instance, scale_levels=network_scale_level + 1)

def constraint_network_cost_rule(instance):
capex = sum(instance.Capex_network[scale_] for scale_ in scale_iter)
vopex = sum(instance.Vopex_network[scale_] for scale_ in scale_iter)
fopex = sum(instance.Fopex_network[scale_] for scale_ in scale_iter)
incidental = sum(
instance.Incidental_network[scale_] for scale_ in scale_iter)

cost_purch = sum(instance.B_network[resource_, scale_] for resource_, scale_ in
product(instance.resources_purch, scale_iter))

if Constraints.LAND in constraints:
land_cost = sum(
instance.Land_cost_network[scale_] for scale_ in scale_iter)
else:
land_cost = 0

if Constraints.CREDIT in constraints:
credit = sum(
instance.Credit_network[scale_] for scale_ in scale_iter)
else:
credit = 0

if len(instance.locations) > 1:
cost_trans = sum(instance.Trans_cost_network[transport_, scale_] for transport_, scale_ in
product(instance.transports, scale_iter))
else:
cost_trans = 0
return instance.Cost == capex + vopex + fopex + cost_purch + cost_trans + incidental + land_cost + credit

instance.constraint_network_cost = Constraint(
rule=constraint_network_cost_rule, doc='total network cost')
constraint_latex_render(constraint_network_cost_rule)
return instance.constraint_network_cost

# *-------------------------Inventory penalty --------------------------


Expand Down Expand Up @@ -915,3 +798,62 @@ def storage_cost_network_rule(instance, *scale_list):
doc='penalty for stored resources across network')
constraint_latex_render(storage_cost_network_rule)
return instance.constraint_storage_cost_network


# *-------------------------Total network cost--------------------------


def constraint_network_cost(instance: ConcreteModel, constraints=Set[Constraints], network_scale_level: int = 0) -> Constraint:
"""Total network costs
Args:
instance (ConcreteModel): pyomo instance
network_scale_level (int, optional): scale of network decisions. Defaults to 0.
Returns:
Constraint: total network cost
"""
scale_iter = scale_tuple(
instance=instance, scale_levels=network_scale_level + 1)

def constraint_network_cost_rule(instance):
capex = sum(instance.Capex_network[scale_] for scale_ in scale_iter)
vopex = sum(instance.Vopex_network[scale_] for scale_ in scale_iter)
fopex = sum(instance.Fopex_network[scale_] for scale_ in scale_iter)
incidental = sum(
instance.Incidental_network[scale_] for scale_ in scale_iter)
storage_cost = sum(
instance.Inv_cost_network[scale_] for scale_ in scale_iter)
cost_purch = sum(instance.B_network[resource_, scale_] for resource_, scale_ in
product(instance.resources_purch, scale_iter))

if Constraints.LAND in constraints:
land_cost = sum(
instance.Land_cost_network[scale_] for scale_ in scale_iter)
else:
land_cost = 0

if Constraints.CREDIT in constraints:
credit = sum(
instance.Credit_network[scale_] for scale_ in scale_iter)
else:
credit = 0

if len(instance.locations) > 1:
cost_trans_capex = sum(
instance.Capex_transport_network[scale_] for scale_ in scale_iter)
cost_trans_vopex = sum(
instance.Vopex_transport_network[scale_] for scale_ in scale_iter)
cost_trans_fopex = sum(
instance.Fopex_transport_network[scale_] for scale_ in scale_iter)
else:
cost_trans_capex = 0
cost_trans_vopex = 0
cost_trans_fopex = 0

return instance.Cost_network == capex + cost_trans_capex + vopex + fopex + cost_purch + cost_trans_vopex + cost_trans_fopex + incidental + land_cost - credit + storage_cost

instance.constraint_network_cost = Constraint(
rule=constraint_network_cost_rule, doc='total network cost')
constraint_latex_render(constraint_network_cost_rule)
return instance.constraint_network_cost
Loading

0 comments on commit caf8a43

Please sign in to comment.