Skip to content

Commit 044052f

Browse files
PatyHidalgostaadecker
authored andcommitted
Merge pull request #83 from staadecker/min_per_type
Add the min_per_tech module
2 parents aff8f2c + 5e6fc2c commit 044052f

File tree

2 files changed

+116
-0
lines changed

2 files changed

+116
-0
lines changed
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
"""
2+
This module allows defining a constraint that specifies a minimum buildout for a certain type of gen_tech.
3+
4+
The advantage of this module is that it stills allows switch to decide where to place
5+
the specified technology.
6+
"""
7+
import os
8+
9+
from pyomo.environ import *
10+
11+
from switch_model.reporting import write_table
12+
13+
14+
def define_components(mod):
15+
mod.GEN_TECH_PER_PERIOD = Set(
16+
initialize=lambda m: m.GENERATION_TECHNOLOGIES * m.PERIODS,
17+
dimen=2,
18+
doc="Set of generation technologies and periods",
19+
)
20+
21+
mod.minimum_capacity_mw = Param(
22+
mod.GEN_TECH_PER_PERIOD,
23+
within=NonNegativeReals,
24+
default=0,
25+
doc="The minimum amount of capacity for a period and generation technology",
26+
)
27+
28+
mod.minimum_energy_capacity_mwh = Param(
29+
mod.GEN_TECH_PER_PERIOD,
30+
within=NonNegativeReals,
31+
default=0,
32+
doc="The minimum amount of energy capacity for a period and generation technology (only considers storage)",
33+
)
34+
35+
mod.GenCapacityPerTech = Expression(
36+
mod.GEN_TECH_PER_PERIOD,
37+
rule=lambda m, tech, p: sum(
38+
m.GenCapacity[g, p] for g in m.GENS_BY_TECHNOLOGY[tech]
39+
),
40+
doc="The amount of power capacity for a period and technology.",
41+
)
42+
43+
mod.GenEnergyCapacityPerTech = Expression(
44+
mod.GEN_TECH_PER_PERIOD,
45+
rule=lambda m, tech, p: sum(
46+
m.StorageEnergyCapacity[g, p]
47+
for g in m.STORAGE_GENS
48+
if m.gen_tech[g] == tech
49+
),
50+
doc="The amount of energy capacity for a period and technology (only considers storage from the storage module).",
51+
)
52+
53+
power_scaling_factor = 1e-4
54+
55+
mod.Enforce_Minimum_Capacity_Per_Tech = Constraint(
56+
mod.GEN_TECH_PER_PERIOD,
57+
rule=lambda m, tech, p: Constraint.Skip
58+
if m.minimum_capacity_mw[tech, p] == 0
59+
else m.GenCapacityPerTech[tech, p] * power_scaling_factor
60+
>= m.minimum_capacity_mw[tech, p] * power_scaling_factor,
61+
doc="Constraint enforcing that the power capacity > minimum",
62+
)
63+
64+
energy_scaling_factor = 1e-5
65+
66+
mod.Enforce_Minimum_Energy_Capacity_Per_Tech = Constraint(
67+
mod.GEN_TECH_PER_PERIOD,
68+
rule=lambda m, tech, p: Constraint.Skip
69+
if m.minimum_energy_capacity_mwh[tech, p] == 0
70+
else m.GenEnergyCapacityPerTech[tech, p] * energy_scaling_factor
71+
>= m.minimum_energy_capacity_mwh[tech, p] * energy_scaling_factor,
72+
doc="Constraint enforcing that the energy capacity > minimum",
73+
)
74+
75+
76+
def load_inputs(mod, switch_data, inputs_dir):
77+
"""
78+
Expected input file:
79+
80+
min_per_tech.csv with the following format:
81+
gen_tech,period,minimum_capacity_mw,minimum_energy_capacity_mwh
82+
Nuclear,2040,10,.
83+
"""
84+
switch_data.load_aug(
85+
filename=os.path.join(inputs_dir, "min_per_tech.csv"),
86+
param=(mod.minimum_capacity_mw, mod.minimum_energy_capacity_mwh),
87+
auto_select=True,
88+
# We want this module to run even if we don't specify a constraint so we still get the useful outputs
89+
optional=True,
90+
optional_params=(mod.minimum_capacity_mw, mod.minimum_energy_capacity_mwh),
91+
)
92+
93+
94+
def post_solve(mod, outdir):
95+
write_table(
96+
mod,
97+
mod.GEN_TECH_PER_PERIOD,
98+
output_file=os.path.join(outdir, "gen_cap_per_tech.csv"),
99+
headings=(
100+
"gen_tech",
101+
"period",
102+
"gen_capacity",
103+
"minimum_capacity_mw",
104+
"energy_capacity",
105+
"minimum_energy_capacity_mwh",
106+
),
107+
values=lambda m, tech, p: (
108+
tech,
109+
p,
110+
m.GenCapacityPerTech[tech, p],
111+
m.minimum_capacity_mw[tech, p],
112+
m.GenEnergyCapacityPerTech[tech, p],
113+
m.minimum_energy_capacity_mwh[tech, p],
114+
),
115+
)

switch_model/wecc/get_inputs/get_inputs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ def write_csv(data: Iterable[List], fname, headers: List[str], log=True):
6767
"switch_model.transmission.transport.dispatch",
6868
"switch_model.policies.carbon_policies",
6969
"switch_model.policies.rps_unbundled",
70+
"switch_model.policies.min_per_tech", # Always include since it provides useful outputs even when unused
7071
# "switch_model.reporting.basic_exports_wecc",
7172
]
7273

0 commit comments

Comments
 (0)