Skip to content

Commit

Permalink
Merge branch 'next_release' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
mfripp authored Oct 27, 2022
2 parents 88abc16 + cbd02d1 commit cbabc82
Show file tree
Hide file tree
Showing 315 changed files with 16,651 additions and 6,718 deletions.
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
*pyc
!.gitignore
.*
*.pyc
**parse_table_datacmds.py
.idea
.DS_Store
gurobi.log
switch_model.egg-info/
venv
Expand Down
29 changes: 22 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
-------------------------------------------------------------------------------
Switch 2.0.7
-------------------------------------------------------------------------------
Note that as of version 5.7, Pyomo no longer supports "inf", "infinity" or "nan"
values in the input files, so Switch will likely report errors if you have
those.

Changed Pyomo dependencies to versions 5.5.1-6.4.2. Note that Pyomo versions
before 5.7.3 don't work with CPLEX version 12.10 or later (see
https://github.com/Pyomo/pyomo/pull/1792). If using a recent version of CPLEX,
you should ensure that you also use version 5.7.3 or later of Pyomo.

Renamed outputs/dispatch-wide.csv to outputs/dispatch_wide.csv

-------------------------------------------------------------------------------
Switch 2.0.6
-------------------------------------------------------------------------------
This release fixes a bug where the fixed costs from all possible build years
were applied each period, instead of only using the build years that are still
in service in the current period. This increased the apparent cost of storage by
approximately (study length) / (storage life). This bug was introduced in
version 2.0.0b3 and persisted through version 2.0.5, so results from earlier
models will need to be updated.
This release fixes a bug where the fixed costs of storage energy capacity (the
MWh part of storage) from all possible build years were mistakenly applied each
period, instead of only using the build years that are still in service in the
current period. This increased the apparent cost of storage by approximately
(study length) / (storage life). This bug was introduced in version 2.0.0b3 and
persisted through version 2.0.5, so results from earlier models will need to be
updated.

This will be the last version of Switch to work in Python 2. It requires at
This will be the last version of Switch to work in Python 2. It requires at
least Python 2.7.12 and also works with Python 3.

-------------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ that they also use to solve models. This supports a number of activities:

To work this way, first install Switch as described above (this will install all
the Switch dependencies, even though you will later reinstall Switch itself).
Then, in a terminal window or Anaconda command prompt Anaconda command prompt,
Then, in a terminal window or Anaconda command prompt,
use the `cd` and `mkdir` commands to create and/or enter the directory where you
would like to store the Switch model code and examples. Once you are in that
directory, run the following commands (don't type the comments that start with
Expand Down
6 changes: 4 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
The Pyomo implementation of the SWITCH model for planning least-cost low-emission electricity grids is licensed under Apache License v2.0 which can be obtained at http://www.apache.org/licenses/LICENSE-2.0
The Switch model for planning least-cost low-emission electricity grids is
licensed under Apache License v2.0 which can be obtained at
http://www.apache.org/licenses/LICENSE-2.0.


Apache License
Expand Down Expand Up @@ -201,4 +203,4 @@ The Pyomo implementation of the SWITCH model for planning least-cost low-emissio
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
limitations under the License.
3 changes: 0 additions & 3 deletions examples/3zone_toy/inputs/balancing_areas.csv

This file was deleted.

6 changes: 3 additions & 3 deletions examples/3zone_toy/inputs/fuel_supply_curves.csv
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
regional_fuel_market,period,tier,unit_cost,max_avail_at_cost
All_DistOil,2020,0,21.9802,inf
All_DistOil,2020,0,21.9802,.
All_DistOil,2030,0,24.5216,100000.0
All_NG,2020,0,4.4647,1950514555.0
All_NG,2020,1,5.0709,inf
All_NG,2020,1,5.0709,.
All_NG,2030,0,5.925,2368354558.0
All_NG,2030,1,5.925,inf
All_NG,2030,1,5.925,.
North_Bio,2020,0,1.7102,6864985.0
North_Bio,2020,1,3.3941,6782413.0
North_Bio,2030,0,2.0438,6064415.0
Expand Down
2 changes: 1 addition & 1 deletion examples/3zone_toy/inputs/gen_build_predetermined.csv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
GENERATION_PROJECT,build_year,gen_predetermined_cap
GENERATION_PROJECT,build_year,build_gen_predetermined
N-Coal_ST,1995,2
N-Geothermal,2000,1
N-NG_CC,2008,2
Expand Down
File renamed without changes.
8 changes: 4 additions & 4 deletions examples/3zone_toy/inputs/load_zones.csv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
LOAD_ZONE,dbid,existing_local_td,local_td_annual_cost_per_mw
North,1,5.5,66406.5
Central,2,3.5,61663.4
South,3,9.5,128040.0
LOAD_ZONE,dbid,existing_local_td,local_td_annual_cost_per_mw,local_td_loss_rate
North,1,5.5,66406.5,0.053
Central,2,3.5,61663.4,0.053
South,3,9.5,128040.0,0.053
2 changes: 1 addition & 1 deletion examples/3zone_toy/inputs/switch_inputs_version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.0.6
2.0.7
4 changes: 2 additions & 2 deletions examples/3zone_toy/inputs/trans_params.csv
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
trans_capital_cost_per_mw_km,trans_lifetime_yrs,trans_fixed_om_fraction,distribution_loss_rate
1000.0,20,0.03,0.053
trans_capital_cost_per_mw_km,trans_lifetime_yrs,trans_fixed_om_fraction
1000.0,20,0.03
2 changes: 1 addition & 1 deletion examples/3zone_toy/outputs/total_cost.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
134733088.429
134733088.42929107
29 changes: 17 additions & 12 deletions examples/3zone_toy_stochastic_PySP/PySPInputGenerator.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"""
from __future__ import print_function

# Inputs directory relative to the location of this script.
inputs_dir = "inputs"
# ScenarioStructure.dat and RootNode.dat will be saved to a
Expand All @@ -58,11 +59,10 @@
stage_list = ["Investment", "Operation"]
stage_vars = {
"Investment": ["BuildGen", "BuildLocalTD", "BuildTx"],
"Operation": ["DispatchGen", "GenFuelUseRate"]
"Operation": ["DispatchGen", "GenFuelUseRate"],
}
# List of scenario names
scenario_list = [
"LowFuelCosts", "MediumFuelCosts", "HighFuelCosts"]
scenario_list = ["LowFuelCosts", "MediumFuelCosts", "HighFuelCosts"]

###########################################################

Expand All @@ -82,6 +82,7 @@
instance = model.load_inputs(inputs_dir=inputs_dir)
print("inputs successfully loaded...")


def save_dat_files():

if not os.path.exists(os.path.join(inputs_dir, pysp_subdir)):
Expand All @@ -92,8 +93,9 @@ def save_dat_files():

dat_file = os.path.join(inputs_dir, pysp_subdir, "RootNode.dat")
print("creating and saving {}...".format(dat_file))
utilities.save_inputs_as_dat(model, instance, save_path=dat_file,
sorted_output=model.options.sorted_output)
utilities.save_inputs_as_dat(
model, instance, save_path=dat_file, sorted_output=model.options.sorted_output
)

#######################
# ScenarioStructure.dat
Expand All @@ -117,7 +119,7 @@ def save_dat_files():

f.write("param NodeStage := RootNode {}\n".format(stage_list[0]))
for s in scenario_list:
f.write(" {scen} {st}\n".format(scen=s,st=stage_list[1]))
f.write(" {scen} {st}\n".format(scen=s, st=stage_list[1]))
f.write(";\n\n")

f.write("set Children[RootNode] := ")
Expand All @@ -127,7 +129,7 @@ def save_dat_files():

f.write("param ConditionalProbability := RootNode 1.0")
# All scenarios have the same probability in this example
probs = [1.0/len(scenario_list)] * (len(scenario_list) - 1)
probs = [1.0 / len(scenario_list)] * (len(scenario_list) - 1)
# The remaining probability is lumped in the last scenario to avoid rounding issues
probs.append(1.0 - sum(probs))
for (s, p) in zip(scenario_list, probs):
Expand All @@ -150,14 +152,16 @@ def write_var_name(f, cname):
if hasattr(instance, cname):
dimen = getattr(instance, cname).index_set().dimen
if dimen == 0:
f.write(" {cn}\n".format(cn=cname))
f.write(" {cn}\n".format(cn=cname))
else:
indexing = (",".join(["*"]*dimen))
indexing = ",".join(["*"] * dimen)
f.write(" {cn}[{dim}]\n".format(cn=cname, dim=indexing))
else:
raise ValueError(
"Variable '{}' is not a component of the model. Did you make a typo?".
format(cname))
"Variable '{}' is not a component of the model. Did you make a typo?".format(
cname
)
)

for st in stage_list:
f.write("set StageVariables[{}] := \n".format(st))
Expand All @@ -171,8 +175,9 @@ def write_var_name(f, cname):
f.write(" Operation OperationCost\n")
f.write(";")


####################

if __name__ == '__main__':
if __name__ == "__main__":
# If the script is executed on the command line, then the .dat files are created.
save_dat_files()
42 changes: 26 additions & 16 deletions examples/3zone_toy_stochastic_PySP/ReferenceModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@

# Ideally, we would use the main codebase to generate the model, but the
# mandatory switch argument parser is interferring with pysp's command line tools
#model = switch_model.solve.main(return_model=True)
# model = switch_model.solve.main(return_model=True)

module_list = switch_model.solve.get_module_list(args=None)
model = utilities.create_model(module_list, args=[])
Expand All @@ -53,14 +53,19 @@
# are nested inside another function in the financials module, they can't
# be called from this script.


def calc_tp_costs_in_period(m, t):
return sum(
getattr(m, tp_cost)[t] * m.tp_weight_in_year[t]
for tp_cost in m.Cost_Components_Per_TP)
return sum(
getattr(m, tp_cost)[t] * m.tp_weight_in_year[t]
for tp_cost in m.Cost_Components_Per_TP
)


def calc_annual_costs_in_period(m, p):
return sum(
getattr(m, annual_cost)[p]
for annual_cost in m.Cost_Components_Per_Period)
return sum(
getattr(m, annual_cost)[p] for annual_cost in m.Cost_Components_Per_Period
)


# In the current version of Switch, all annual costs are defined
# by First Stage decision variables, such as fixed O&M and capital
Expand All @@ -73,14 +78,19 @@ def calc_annual_costs_in_period(m, p):
# decisions in this example.
# Further comments on this are written in the Readme file.

model.InvestmentCost = Expression(rule=lambda m: sum(
calc_annual_costs_in_period(m, p) * m.bring_annual_costs_to_base_year[p]
for p in m.PERIODS))

model.OperationCost = Expression(rule=lambda m:
sum(
sum(calc_tp_costs_in_period(m, t) for t in m.TPS_IN_PERIOD[p]
) * m.bring_annual_costs_to_base_year[p]
for p in m.PERIODS))
model.InvestmentCost = Expression(
rule=lambda m: sum(
calc_annual_costs_in_period(m, p) * m.bring_annual_costs_to_base_year[p]
for p in m.PERIODS
)
)

model.OperationCost = Expression(
rule=lambda m: sum(
sum(calc_tp_costs_in_period(m, t) for t in m.TPS_IN_PERIOD[p])
* m.bring_annual_costs_to_base_year[p]
for p in m.PERIODS
)
)

print("model successfully loaded...")
3 changes: 0 additions & 3 deletions examples/3zone_toy_stochastic_PySP/inputs/balancing_areas.csv

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
GENERATION_PROJECT,build_year,gen_predetermined_cap
GENERATION_PROJECT,build_year,build_gen_predetermined
N-Coal_ST,1995,2
N-Geothermal,2000,1
N-NG_CC,2008,2
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.0.6
2.0.7
11 changes: 8 additions & 3 deletions examples/3zone_toy_stochastic_PySP/pha_bounds_cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,24 @@
# Use this by adding terms like the following to the runph command:
# --linearize-nonbinary-penalty-terms=5 --bounds-cfgfile=pha_bounds_cfg.py


def pysp_boundsetter_callback(self, scenario_tree, scenario):
m = scenario._instance # see pyomo/pysp/scenariotree/tree_structure.py
m = scenario._instance # see pyomo/pysp/scenariotree/tree_structure.py

# BuildLocalTD
for p in m.PERIODS:
for lz in m.LOAD_ZONES:
m.BuildLocalTD[lz, p].setub(2 * m.zone_expected_coincident_peak_demand[lz, p])
m.BuildLocalTD[lz, p].setub(
2 * m.zone_expected_coincident_peak_demand[lz, p]
)

# Estimate an upper bound of system peak demand for limiting generation unit
# & transmission line builds
system_wide_peak = {}
for p in m.PERIODS:
system_wide_peak[p] = sum(
m.zone_expected_coincident_peak_demand[lz, p] for lz in m.LOAD_ZONES)
m.zone_expected_coincident_peak_demand[lz, p] for lz in m.LOAD_ZONES
)

# BuildGen
for g, bld_yr in m.NEW_GEN_BLD_YRS:
Expand All @@ -27,6 +31,7 @@ def pysp_boundsetter_callback(self, scenario_tree, scenario):
for tx, bld_yr in m.TRANS_BLD_YRS:
m.BuildTx[tx, bld_yr].setub(5 * system_wide_peak[bld_yr])


# For some reason runph looks for pysp_boundsetter_callback when run in
# single-thread mode and ph_boundsetter_callback when called from mpirun with
# remote execution via pyro. so we map both names to the same function.
Expand Down
28 changes: 17 additions & 11 deletions examples/3zone_toy_stochastic_PySP/rhosetter.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,22 @@
from switch_model.utilities import iteritems

try:
from pyomo.repn import generate_standard_repn # Pyomo >=5.6
from pyomo.repn import generate_standard_repn # Pyomo >=5.6

newPyomo = True
except ImportError:
from pyomo.repn import generate_canonical_repn # Pyomo <=5.6
from pyomo.repn import generate_canonical_repn # Pyomo <=5.6

newPyomo = False


def ph_rhosetter_callback(ph, scenario_tree, scenario):
# Derive coefficients from active objective
cost_expr = next(scenario._instance.component_data_objects(
Objective, active=True, descend_into=True
))
# Derive coefficients from active objective
cost_expr = next(
scenario._instance.component_data_objects(
Objective, active=True, descend_into=True
)
)
set_rho_values(ph, scenario_tree, scenario, cost_expr)


Expand Down Expand Up @@ -57,8 +62,7 @@ def set_rho_values(ph, scenario_tree, scenario, cost_expr):

cost_coefficients = {}
var_names = {}
for (variable, coef) in \
zip(standard_repn.linear_vars, standard_repn.linear_coefs):
for (variable, coef) in zip(standard_repn.linear_vars, standard_repn.linear_coefs):
variable_id = symbol_map.getSymbol(variable)
cost_coefficients[variable_id] = coef
var_names[variable_id] = variable.name
Expand All @@ -72,11 +76,13 @@ def set_rho_values(ph, scenario_tree, scenario, cost_expr):
tree_node,
scenario,
variable_id,
cost_coefficients[variable_id] * rho_coefficient)
cost_coefficients[variable_id] * rho_coefficient,
)
set_rho = True
break
if not set_rho:
print(
"Warning! Could not find tree node for variable {}; rho not set."
.format(var_names[variable_id])
"Warning! Could not find tree node for variable {}; rho not set.".format(
var_names[variable_id]
)
)
1 change: 1 addition & 0 deletions examples/3zone_toy_stochastic_PySP/rhosetter_FS_only.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
# The rhosetter module should be in the same directory as this file.
from rhosetter import set_rho_values


def ph_rhosetter_callback(ph, scenario_tree, scenario):
# This component name must match the expression used for first stage
# costs defined in the ReferenceModel.
Expand Down
3 changes: 0 additions & 3 deletions examples/carbon_cap/inputs/balancing_areas.csv

This file was deleted.

Loading

0 comments on commit cbabc82

Please sign in to comment.