Skip to content

Commit 9e4011e

Browse files
committed
Merge branch 'add_generation_groups' into improv_hydro
# Conflicts: # switch_model/solve.py
2 parents f5109f6 + f3a1ae6 commit 9e4011e

18 files changed

+376
-207
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
####################
3+
Add generation plants groups
4+
5+
Date applied:
6+
Description:
7+
This script adds the option to specify generation plant groups.
8+
The generation groups are specified in the table generation_plant_group.
9+
Plants are assigned to a group by adding them to the many-to-many table generation_plant_group_member.
10+
Groups are assigned to a generation_plant_scenario_id by specifying them in generation_plant_scenario_group_member
11+
#################
12+
*/
13+
14+
CREATE TABLE switch.generation_plant_group
15+
(
16+
generation_plant_group_id serial NOT NULL,
17+
description text NOT NULL,
18+
name character varying(30) NOT NULL,
19+
PRIMARY KEY (generation_plant_group_id)
20+
);
21+
22+
COMMENT ON TABLE switch.generation_plant_group
23+
IS 'This table specifies all the generation plant groups. Every group has a set of generation plants (see generation_plant_group_member). Groups can be assigned to a generation_plant_scenario (see generation_plant_scenario_group_member).';
24+
25+
CREATE TABLE switch.generation_plant_group_member
26+
(
27+
generation_plant_group_id integer,
28+
generation_plant_id integer,
29+
PRIMARY KEY (generation_plant_group_id, generation_plant_id)
30+
);
31+
32+
ALTER TABLE switch.generation_plant_group_member
33+
ADD CONSTRAINT generation_plant_group_member_group_id_fkey
34+
FOREIGN KEY (generation_plant_group_id)
35+
REFERENCES switch.generation_plant_group (generation_plant_group_id);
36+
37+
ALTER TABLE switch.generation_plant_group_member
38+
ADD CONSTRAINT generation_plant_group_member_generation_plant_id_fkey
39+
FOREIGN KEY (generation_plant_id)
40+
REFERENCES switch.generation_plant (generation_plant_id);
41+
42+
COMMENT ON TABLE switch.generation_plant_group_member
43+
IS 'This table is a many-to-many table that specifies the generation plants that are associated with a generation group.';
44+
45+
CREATE TABLE switch.generation_plant_scenario_group_member
46+
(
47+
generation_plant_scenario_id integer,
48+
generation_plant_group_id integer,
49+
PRIMARY KEY (generation_plant_scenario_id, generation_plant_group_id)
50+
);
51+
52+
ALTER TABLE switch.generation_plant_scenario_group_member
53+
ADD CONSTRAINT generation_plant_scenario_group_member_scenario_id_fkey
54+
FOREIGN KEY (generation_plant_scenario_id)
55+
REFERENCES switch.generation_plant_scenario (generation_plant_scenario_id);
56+
57+
ALTER TABLE switch.generation_plant_scenario_group_member
58+
ADD CONSTRAINT generation_plant_scenario_group_member_group_id_fkey
59+
FOREIGN KEY (generation_plant_group_id)
60+
REFERENCES switch.generation_plant_group (generation_plant_group_id);
61+
62+
COMMENT ON TABLE switch.generation_plant_scenario_group_member
63+
IS 'This table is a many-to-many table that specifies which generation plant groups belong to which generation plant scenarios';
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
####################
3+
Add column gen_store_energy_to_power_ratio
4+
5+
Date applied: 2021-06-18
6+
Description:
7+
This script adds a column to the generation_plant
8+
table called gen_storage_energy_to_power_ratio specifying
9+
the storage duration
10+
#################
11+
*/
12+
13+
ALTER TABLE switch.generation_plant ADD COLUMN gen_storage_energy_to_power_ratio real;

switch_model/__main__.py

Lines changed: 59 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -4,74 +4,70 @@
44
"""Script to handle switch <cmd> calls from the command line."""
55
from __future__ import print_function
66

7-
import sys, os
7+
import argparse
8+
import importlib
9+
import sys
810
import switch_model
11+
from switch_model.utilities import get_git_branch
12+
13+
def version():
14+
print("Switch model version " + switch_model.__version__)
15+
branch = get_git_branch()
16+
if branch is not None:
17+
print(f"Switch Git branch: {branch}")
18+
return 0
19+
20+
def help_text():
21+
print(
22+
f"Must specifiy one of the following commands: {list(cmds.keys())}.\nE.g. Run 'switch solve' or 'switch get_inputs'.")
23+
24+
25+
def get_module_runner(module):
26+
def runner():
27+
importlib.import_module(module).main()
28+
return runner
29+
30+
31+
cmds = {
32+
"solve": get_module_runner("switch_model.solve"),
33+
"solve-scenarios": get_module_runner("switch_model.solve_scenarios"),
34+
"test": get_module_runner("switch_model.test"),
35+
"upgrade": get_module_runner("switch_model.upgrade"),
36+
"get_inputs": get_module_runner("switch_model.wecc.get_inputs"),
37+
"drop": get_module_runner("switch_model.tools.drop"),
38+
"new": get_module_runner("switch_model.tools.new"),
39+
"graph": get_module_runner("switch_model.tools.graph.cli_graph"),
40+
"compare": get_module_runner("switch_model.tools.graph.cli_compare"),
41+
"db": get_module_runner("switch_model.wecc.__main__"),
42+
"help": help_text
43+
}
944

1045

1146
def main():
12-
# TODO make a proper command line tool with help information for each option
13-
cmds = [
14-
"solve",
15-
"solve-scenarios",
16-
"test",
17-
"upgrade",
18-
"get_inputs",
19-
"--version",
20-
"drop",
21-
"new",
22-
"graph",
23-
"compare",
24-
"sampling",
25-
]
26-
if len(sys.argv) >= 2 and sys.argv[1] in cmds:
27-
# If users run a script from the command line, the location of the script
28-
# gets added to the start of sys.path; if they call a module from the
29-
# command line then an empty entry gets added to the start of the path,
30-
# indicating the current working directory. This module is often called
31-
# from a command-line script, but we want the current working
32-
# directory in the path because users may try to load local modules via
33-
# the configuration files, so we make sure that's always in the path.
34-
sys.path[0] = ""
35-
36-
# adjust the argument list to make it look like someone ran "python -m <module>" directly
37-
cmd = sys.argv[1]
38-
sys.argv[0] += " " + cmd
47+
parser = argparse.ArgumentParser(add_help=False)
48+
parser.add_argument("--version", default=False, action="store_true", help="Get version info")
49+
parser.add_argument("subcommand", choices=cmds.keys(), help="The possible switch subcommands", nargs="?",
50+
default="help")
51+
52+
# If users run a script from the command line, the location of the script
53+
# gets added to the start of sys.path; if they call a module from the
54+
# command line then an empty entry gets added to the start of the path,
55+
# indicating the current working directory. This module is often called
56+
# from a command-line script, but we want the current working
57+
# directory in the path because users may try to load local modules via
58+
# the configuration files, so we make sure that's always in the path.
59+
sys.path[0] = ""
60+
61+
args, remaining_args = parser.parse_known_args()
62+
63+
if args.version:
64+
return version()
65+
66+
# adjust the argument list to make it look like someone ran "python -m <module>" directly
67+
if len(sys.argv) > 1:
68+
sys.argv[0] += " " + sys.argv[1]
3969
del sys.argv[1]
40-
if cmd == "--version":
41-
print("Switch model version " + switch_model.__version__)
42-
from switch_model.utilities import get_git_branch
43-
branch = get_git_branch()
44-
if branch is not None:
45-
print(f"Switch Git branch: {branch}")
46-
return 0
47-
if cmd == "solve":
48-
from switch_model.solve import main
49-
elif cmd == "solve-scenarios":
50-
from switch_model.solve_scenarios import main
51-
elif cmd == "test":
52-
from switch_model.test import main
53-
elif cmd == "upgrade":
54-
from switch_model.upgrade import main
55-
elif cmd == "get_inputs":
56-
from switch_model.wecc.get_inputs import main
57-
elif cmd == "sampling":
58-
from switch_model.wecc.sampling import main
59-
elif cmd == "drop":
60-
from switch_model.tools.drop import main
61-
elif cmd == "new":
62-
from switch_model.tools.new import main
63-
elif cmd == "graph":
64-
from switch_model.tools.graph.cli_graph import main
65-
elif cmd == "compare":
66-
from switch_model.tools.graph.cli_compare import main
67-
main()
68-
else:
69-
print(
70-
"Usage: {} {{{}}} ...".format(
71-
os.path.basename(sys.argv[0]), ", ".join(cmds)
72-
)
73-
)
74-
print("Use one of these commands with --help for more information.")
70+
cmds[args.subcommand]()
7571

7672

7773
if __name__ == "__main__":

switch_model/generators/core/dispatch.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import os, collections
2222

23+
from pyomo.core.base.misc import sorted_robust
2324
from pyomo.environ import *
2425
import pandas as pd
2526

@@ -403,16 +404,18 @@ def post_solve(instance, outdir):
403404
dispatch_annual_summary.pdf - A figure of annual summary data. Only written
404405
if the ggplot python library is installed.
405406
"""
407+
sorted_gen = sorted_robust(instance.GENERATION_PROJECTS)
406408
write_table(
407409
instance, instance.TIMEPOINTS,
408410
output_file=os.path.join(outdir, "dispatch-wide.csv"),
409-
headings=("timestamp",) + tuple(sorted(instance.GENERATION_PROJECTS)),
411+
headings=("timestamp",) + tuple(sorted_gen),
410412
values=lambda m, t: (m.tp_timestamp[t],) + tuple(
411413
m.DispatchGen[p, t] if (p, t) in m.GEN_TPS
412414
else 0.0
413-
for p in sorted(m.GENERATION_PROJECTS)
415+
for p in sorted_gen
414416
)
415417
)
418+
del sorted_gen
416419

417420
def c(func):
418421
return (value(func(g, t)) for g, t in instance.GEN_TPS)

switch_model/reporting/__init__.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
2020
"""
2121
from __future__ import print_function
22-
from switch_model.utilities import string_types, add_info
22+
from pyomo.core.base.misc import sorted_robust
23+
from switch_model.utilities import string_types
24+
from switch_model.utilities.results_info import add_info
2325
from switch_model.utilities.scaling import get_unscaled_var
2426
dependencies = 'switch_model.financials'
2527

@@ -93,7 +95,7 @@ def write_table(instance, *indexes, output_file=None, **kwargs):
9395
try:
9496
rows = (format_row(values(instance, *unpack_elements(x)), cell_formatter) for x in
9597
itertools.product(*indexes))
96-
w.writerows(sorted(rows) if instance.options.sorted_output else rows)
98+
w.writerows(sorted_robust(rows) if instance.options.sorted_output else rows)
9799
except TypeError: # lambda got wrong number of arguments
98100
# use old code, which doesn't unpack the indices
99101
w.writerows(
@@ -166,7 +168,7 @@ def save_generic_results(instance, outdir, sorted_output):
166168
[var.name])
167169
# Results are saved in a random order by default for
168170
# increased speed. Sorting is available if wanted.
169-
items = sorted(var.items()) if sorted_output else list(var.items())
171+
items = sorted_robust(var.items()) if sorted_output else list(var.items())
170172
for key, obj in items:
171173
writer.writerow(format_row(tuple(make_iterable(key)) + (obj,), cell_formatter))
172174
else:

0 commit comments

Comments
 (0)