Skip to content

Commit d2e7456

Browse files
pesapstaadecker
authored andcommitted
Merge pull request #88 from staadecker/improve_load_aug
Improve loading inputs and docs
2 parents d84a114 + 82058ff commit d2e7456

File tree

26 files changed

+1186
-851
lines changed

26 files changed

+1186
-851
lines changed

README.md

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,41 @@
33
Welcome! This repository contains the SWITCH electricity planning model adapted for the
44
REAM research lab.
55

6-
For **an overview** of what SWITCH is and how it works, read [`docs/Overview.md`](./docs/Overiew.md).
6+
## Available documentation
77

8-
To discover **how to install, run or debug** the different components of Switch, read [`docs/Usage.md`](./docs/Usage.md)
8+
In `docs/`:
99

10-
To **see examples** of smaller SWITCH models, see the `examples/` folder.
10+
- [`Overview.md`](./docs/Overiew.md): An overview of what SWITCH is and how it works, read
1111

12-
To discover **how to contribute to the model**, read [`docs/Contribute.md`](/docs/Contribute.md)
12+
- [`Usage.md`](./docs/Usage.md): How to install, run or debug the different components of Switch
1313

14-
To **learn about our database** (e.g. how to connect to it and modify it), read [`docs/Database.md`](/docs/Database.md).
14+
- [`Developing Modules.md`](./docs/Developing%20Modules.md): How to create SWITCH modules from scratch
1515

16-
To **generate documentation**, run `pydoc -w switch_model` after having installed
16+
- [`Contribute.md`](/docs/Contribute.md): How to contribute code to the project.
17+
18+
- [`Graphs`](/docs/Graphs.md): How to create new graphs to analyze your results.
19+
20+
- [`Database.md`](/docs/Database.md): All about the REAM database (e.g. how to connect to it and modify it)
21+
22+
- [`Numerical Solvers.md`](/docs/Numerical%20Solvers.md): Information about numerical solvers, specifically Gurobi.
23+
24+
- [`Numerical Issues.md`](/docs/Numerical%20Issues.md): Information about detecting and resolving numerical issues.
25+
26+
Finally, you can generate documentation for the SWITCH modules by running `pydoc -w switch_model` after having installed
1727
SWITCH. This will build HTML documentation files from python doc strings which
1828
will include descriptions of each module, their intentions, model
1929
components they define, and what input files they expect.
2030

21-
To learn about **numerical solvers** read [`docs/Numerical Solvers.md`](/docs/Numerical%20Solvers.md)
31+
## Key folders
32+
33+
- [`/database`](/database) Folder containing SQL scripts and files that keep track of updates to our PostgreSQL database.
34+
35+
- [`/examples`](/examples) Folder with numerous examples of SWITCH projects often used for testing.
36+
37+
- [`/switch_model`](/switch_model) Folder containing all the source code for the SWITCH modules.
38+
39+
- [`/switch_model/wecc`](/switch_model/wecc) Folder containing modules specific to the REAM team.
40+
41+
- [`/switch_model/wecc/get_inputs`](/switch_model/wecc/get_inputs) Scripts that fetch the input data from the PostgreSQL database.
2242

23-
To learn about **numerical issues** read [`docs/Numerical Issues.md`](/docs/Numerical%20Issues.md)
43+
- [`/tests`](/tests) Folder containing tests for SWITCH. Can be run via `python run_tests.py`.

docs/Contribute.md

Lines changed: 4 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Contributing Code
22

3-
This document describes the best practices for contributing code.
3+
You've made changes to the codebase and now you want to share them
4+
with the rest of the team! Here are the best practices for the process.
45

56
## The process
67

@@ -39,43 +40,6 @@ supposed to alter the results of the examples, you'll need
3940
to follow the instructions that appear on screen to suppress the errors
4041
produced by `python run_tests.py`.
4142

42-
## Contributing graphs
43+
## Important notes
4344

44-
Read [`docs/Graphs.md`](./Graphs.md) to see learn to add graphs.
45-
46-
## Modifying the database
47-
48-
Read [`docs/Database.md`](./Database.md) to learn about the database.
49-
50-
## Outputting results
51-
52-
Once the model is solved, the `post_solve()` function in each module is called.
53-
Within the `post_solve()` function you may
54-
55-
- Call `write_table()` to create
56-
a .csv file with data from the solution (see existing modules for examples).
57-
58-
- Call `add_info()` (from `utilities/result_info.py`) to add a line
59-
of information to the `outputs/info.txt` file. `add_info()` can also be added to `graph()`.
60-
61-
### Example
62-
63-
```python
64-
from switch_model.utilities.results_info import add_info
65-
from switch_model.reporting import write_table
66-
import os
67-
...
68-
def post_solve(instance, outdir):
69-
...
70-
# This will add the a line to info.txt in the outputs folder
71-
add_info("Some important value", instance.important_value)
72-
...
73-
# This will create my_table.csv
74-
write_table(
75-
instance,
76-
instance.TIMEPOINTS, # Set that the values function will iterate over
77-
output_file=os.path.join(outdir, "my_table.csv"),
78-
headings=("timepoint", "some value"),
79-
values=lambda m, t: (t, m.some_value[t])
80-
)
81-
```
45+
- If your change is modifying the database, make sure you've read [`Database.md`](./Database.md).

docs/Developing Modules.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
## Developing modules
2+
3+
Modules are the core elements of SWITCH. Each module defines a specific functionality for the model. For example,
4+
the `switch_model.generators.core.build` defines how generators are allowed to be built while `switch_model.timescales`
5+
defines how time is handled in SWITCH.
6+
7+
There are 3 important parts to any module.
8+
9+
1. `define_components(model)`: This function specifies the Pyomo Sets, Parameters, Variables and Expressions for the module
10+
as well as the input files that should be used. It's the first thing that gets called when you run `switch solve` as
11+
it creates the Pyomo model.
12+
13+
2. `post_solve()`: This function gets run after the solver has found the optimal solution. This is where you can output
14+
results to e.g. a csv file.
15+
16+
3. Functions with the `@graph(...)` decorator. These functions get called last and are responsible for creating graphs
17+
for analysis using the data from the csv files you created in `post_solve()`.
18+
19+
There are also a few other components that you may encounter:
20+
21+
- `load_inputs()`: This function is the old way of loading inputs from .csv files into the model. It gets called right
22+
after `define_components()`. Now the prefered way of loading inputs is by using `input_file=`
23+
(see next section for details).
24+
25+
- `define_dynamic_lists(model)` and `define_dynamic_components(model)`:
26+
Some modules need to define objects to be shared across multiple modules.
27+
The best example of this is `switch_model.balancing.load_zones` which
28+
allows different modules to add elements to a dynamic list that is defined
29+
in `define_dynamic_lists`. Then in `define_dynamic_components` it defines
30+
the energy balance constraint using the dynamic list. See the module for details.
31+
32+
## Writing `define_components()`
33+
34+
`define_components(mod)` takes in the model as an argument and is responsible
35+
for adding constraints, expressions, variables, sets or parameters to the model.
36+
37+
Sometimes Sets or Parameters should be initialized from an input csv file.
38+
If this is the case, add `input_file=` (and optionally `input_column`) to the
39+
set or parameter definition.
40+
41+
For example the following code snippet defines a Set and a parameter
42+
indexed over that set. Both the set and parameter are initialized from
43+
the `input.csv` file.
44+
45+
```python
46+
from pyomo.environ import *
47+
48+
49+
def define_components(mod):
50+
mod.SetA = Set(
51+
dimen=2,
52+
input_file="input.csv",
53+
)
54+
55+
mod.some_indexed_param = Param(
56+
mod.SetA,
57+
input_file="input.csv",
58+
input_column="param1" # only specify when the name of the column in the csv is not the same as the component name
59+
)
60+
```
61+
62+
## Writing `post_solve()`
63+
64+
Once the model is solved, the `post_solve()` function in each module is called. Within the `post_solve()` function you
65+
may
66+
67+
- Call `write_table()` to create a .csv file with data from the solution (see existing modules for examples).
68+
69+
- Call `add_info()` (from `utilities/result_info.py`) to add a line of information to the `outputs/info.txt`
70+
file. `add_info()` can also be added to `graph()`.
71+
72+
### Example
73+
74+
```python
75+
from switch_model.utilities.results_info import add_info
76+
from switch_model.reporting import write_table
77+
import os
78+
79+
...
80+
81+
82+
def post_solve(instance, outdir):
83+
...
84+
# This will add the a line to info.txt in the outputs folder
85+
add_info("Some important value", instance.important_value)
86+
...
87+
# This will create my_table.csv
88+
write_table(
89+
instance,
90+
instance.TIMEPOINTS, # Set that the values function will iterate over
91+
output_file=os.path.join(outdir, "my_table.csv"),
92+
headings=("timepoint", "some value"),
93+
values=lambda m, t: (t, m.some_value[t])
94+
)
95+
```

switch_model/balancing/demand_response/simple.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
demand shifting. This does not include a Shed Service (curtailment of load),
99
nor a Shimmy Service (fast dispatch for load following or regulation).
1010
11+
INPUT FILE FORMAT
12+
Import demand response-specific data from an input directory.
13+
14+
dr_data.csv
15+
LOAD_ZONE, TIMEPOINT, dr_shift_down_limit, dr_shift_up_limit
1116
"""
1217

1318
import os
@@ -53,11 +58,21 @@ def define_components(mod):
5358
mod.TIMEPOINTS,
5459
default=0.0,
5560
within=NonNegativeReals,
61+
<<<<<<< HEAD
5662
validate=lambda m, value, z, t: value <= m.zone_demand_mw[z, t],
5763
)
5864
mod.dr_shift_up_limit = Param(
5965
mod.LOAD_ZONES, mod.TIMEPOINTS, default=float("inf"), within=NonNegativeReals
6066
)
67+
=======
68+
input_file="dr_data.csv",
69+
validate=lambda m, value, z, t: value <= m.zone_demand_mw[z, t])
70+
mod.dr_shift_up_limit = Param(
71+
mod.LOAD_ZONES, mod.TIMEPOINTS,
72+
default= float('inf'),
73+
input_file="dr_data.csv",
74+
within=NonNegativeReals)
75+
>>>>>>> 941c8e2e (Further improvements)
6176
mod.ShiftDemand = Var(
6277
mod.LOAD_ZONES,
6378
mod.TIMEPOINTS,
@@ -77,6 +92,7 @@ def define_components(mod):
7792
try:
7893
mod.Distributed_Power_Withdrawals.append("ShiftDemand")
7994
except AttributeError:
95+
<<<<<<< HEAD
8096
mod.Zone_Power_Withdrawals.append("ShiftDemand")
8197

8298

@@ -96,3 +112,6 @@ def load_inputs(mod, switch_data, inputs_dir):
96112
autoselect=True,
97113
param=(mod.dr_shift_down_limit, mod.dr_shift_up_limit),
98114
)
115+
=======
116+
mod.Zone_Power_Withdrawals.append('ShiftDemand')
117+
>>>>>>> 941c8e2e (Further improvements)

switch_model/balancing/electric_vehicles/simple.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@
1111
of each timeseries they must be charged at some specific level according
1212
to users necessity.
1313
14+
INPUT FILE FORMAT
15+
Import virtual batteries specific location and power limits
16+
from an input directory.
17+
18+
ev_limits.tab
19+
LOAD_ZONES, TIMEPOINT, ev_cumulative_charge_upper_mwh,
20+
ev_cumulative_charge_upper_mwh, ev_charge_limit_mw
1421
"""
1522

1623
import os
@@ -66,6 +73,7 @@ def define_components(mod):
6673
"""
6774

6875
mod.ev_charge_limit_mw = Param(
76+
<<<<<<< HEAD
6977
mod.LOAD_ZONES, mod.TIMEPOINTS, default=float("inf"), within=NonNegativeReals
7078
)
7179

@@ -76,6 +84,24 @@ def define_components(mod):
7684
mod.ev_cumulative_charge_lower_mwh = Param(
7785
mod.LOAD_ZONES, mod.TIMEPOINTS, default=0.0, within=NonNegativeReals
7886
)
87+
=======
88+
mod.LOAD_ZONES, mod.TIMEPOINTS,
89+
default = float('inf'),
90+
input_file="ev_limits.csv",
91+
within=NonNegativeReals)
92+
93+
mod.ev_cumulative_charge_upper_mwh = Param(
94+
mod.LOAD_ZONES, mod.TIMEPOINTS,
95+
default = 0.0,
96+
input_file="ev_limits.csv",
97+
within=NonNegativeReals)
98+
99+
mod.ev_cumulative_charge_lower_mwh = Param(
100+
mod.LOAD_ZONES, mod.TIMEPOINTS,
101+
default = 0.0,
102+
input_file="ev_limits.csv",
103+
within=NonNegativeReals)
104+
>>>>>>> 941c8e2e (Further improvements)
79105

80106
mod.EVCharge = Var(
81107
mod.LOAD_ZONES,
@@ -111,6 +137,7 @@ def define_components(mod):
111137
if "Distributed_Power_Injections" in dir(mod):
112138
mod.Distributed_Power_Withdrawals.append("EVCharge")
113139
else:
140+
<<<<<<< HEAD
114141
mod.Zone_Power_Withdrawals.append("EVCharge")
115142

116143

@@ -136,3 +163,6 @@ def load_inputs(mod, switch_data, inputs_dir):
136163
mod.ev_charge_limit_mw,
137164
),
138165
)
166+
=======
167+
mod.Zone_Power_Withdrawals.append('EVCharge')
168+
>>>>>>> 941c8e2e (Further improvements)

0 commit comments

Comments
 (0)