Skip to content

Commit

Permalink
Ported some doctests out of utilities into proper unit tests to make …
Browse files Browse the repository at this point in the history
…them more robust. They had been failing off and on for a while, especially when pyomo changed its output formatting. I also tweaked the "no emissions" value in dispatch export from None to zero to avoid a weird pandas Future warning that occurred in the examples/storage test when every value in the emissions column was None.
  • Loading branch information
josiahjohnston committed Feb 16, 2018
1 parent d0122f6 commit 968c98e
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 77 deletions.
12 changes: 6 additions & 6 deletions examples/storage/outputs/dispatch.csv
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
generation_project,timestamp,DispatchEmissions_tCO2_per_typical_yr,DispatchGen_MW,Energy_GWh_typical_yr,VariableCost_per_yr,gen_dbid,gen_energy_source,gen_load_zone,gen_tech,period,tp_weight_in_year_hrs
S-Geothermal,2025011600,,4.44411428571,19.4785529143,561566.680519,33.0,Geothermal,South,Geothermal,2020,4383.0
S-Geothermal,2025011512,,4.44411428571,19.4785529143,561566.680519,33.0,Geothermal,South,Geothermal,2020,4383.0
S-Central_PV-1,2025011600,,0.0,0.0,0.0,41.0,Solar,South,Central_PV,2020,4383.0
Battery_Storage,2025011512,,2.95808571429,12.9652896857,129.652896857,Battery_Storage,Electricity,South,Battery_Storage,2020,4383.0
S-Central_PV-1,2025011512,,0.5978,2.6201574,0.0,41.0,Solar,South,Central_PV,2020,4383.0
Battery_Storage,2025011600,,0.0,0.0,0.0,Battery_Storage,Electricity,South,Battery_Storage,2020,4383.0
S-Geothermal,2025011600,0,4.44411428571429,19.478552914285736,561566.6805188577,33.0,Geothermal,South,Geothermal,2020,4383.0
S-Geothermal,2025011512,0,4.44411428571429,19.478552914285736,561566.6805188577,33.0,Geothermal,South,Geothermal,2020,4383.0
S-Central_PV-1,2025011600,0,0.0,0.0,0.0,41.0,Solar,South,Central_PV,2020,4383.0
Battery_Storage,2025011512,0,2.95808571428571,12.965289685714268,129.65289685714268,Battery_Storage,Electricity,South,Battery_Storage,2020,4383.0
S-Central_PV-1,2025011512,0,0.5978,2.6201574,0.0,41.0,Solar,South,Central_PV,2020,4383.0
Battery_Storage,2025011600,0,0.0,0.0,0.0,Battery_Storage,Electricity,South,Battery_Storage,2020,4383.0
6 changes: 3 additions & 3 deletions examples/storage/outputs/dispatch_annual_summary.csv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
gen_tech,gen_energy_source,period,Energy_GWh_typical_yr,VariableCost_per_yr,DispatchEmissions_tCO2_per_typical_yr
Battery_Storage,Electricity,2020,12.9652896857,129.652896857,
Central_PV,Solar,2020,2.6201574,0.0,
Geothermal,Geothermal,2020,38.9571058286,1123133.36104,
Battery_Storage,Electricity,2020,12.965289685714268,129.65289685714268,0
Central_PV,Solar,2020,2.6201574,0.0,0
Geothermal,Geothermal,2020,38.95710582857147,1123133.3610377153,0
6 changes: 3 additions & 3 deletions examples/storage/outputs/dispatch_zonal_annual_summary.csv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
gen_tech,gen_load_zone,gen_energy_source,period,Energy_GWh_typical_yr,VariableCost_per_yr,DispatchEmissions_tCO2_per_typical_yr
Battery_Storage,South,Electricity,2020,12.9652896857,129.652896857,
Central_PV,South,Solar,2020,2.6201574,0.0,
Geothermal,South,Geothermal,2020,38.9571058286,1123133.36104,
Battery_Storage,South,Electricity,2020,12.965289685714268,129.65289685714268,0
Central_PV,South,Solar,2020,2.6201574,0.0,0
Geothermal,South,Geothermal,2020,38.95710582857147,1123133.3610377153,0
2 changes: 1 addition & 1 deletion switch_model/generators/core/dispatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ def post_solve(instance, outdir):
"DispatchEmissions_tCO2_per_typical_yr": value(sum(
instance.DispatchEmissions[g, t, f] * instance.tp_weight_in_year[t]
for f in instance.FUELS_FOR_GEN[g]
)) if instance.gen_uses_fuel[g] else None
)) if instance.gen_uses_fuel[g] else 0
} for g, t in instance.GEN_TPS ]
dispatch_full_df = pd.DataFrame(dispatch_normalized_dat)
dispatch_full_df.set_index(["generation_project", "timestamp"], inplace=True)
Expand Down
64 changes: 0 additions & 64 deletions switch_model/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,36 +263,9 @@ def min_data_check(model, *mandatory_model_components):

def _add_min_data_check(model):
"""
Bind the min_data_check() method to an instance of a Pyomo AbstractModel
object if it has not already been added. Also add a counter to keep
track of what to name the next check that is added.
>>> from switch_model.utilities import _add_min_data_check
>>> mod = AbstractModel()
>>> _add_min_data_check(mod)
>>> mod.set_A = Set(initialize=[1,2])
>>> mod.paramA_full = Param(mod.set_A, initialize={1:'a',2:'b'})
>>> mod.paramA_empty = Param(mod.set_A)
>>> mod.min_data_check('set_A', 'paramA_full')
>>> if hasattr(mod, 'create_instance'):
... instance_pass = mod.create_instance()
... else:
... instance_pass = mod.create()
>>> mod.min_data_check('set_A', 'paramA_empty')
>>> try:
... if hasattr(mod, 'create_instance'):
... instance_fail = mod.create_instance()
... else:
... instance_fail = mod.create()
... except ValueError as e:
... print e # doctest: +NORMALIZE_WHITESPACE
ERROR: Constructing component 'min_data_check_2' from data=None failed:
ValueError: Values are not provided for every element of the mandatory
parameter 'paramA_empty'. Missing data for 2 values, including: [1, 2]
Values are not provided for every element of the mandatory parameter
'paramA_empty'. Missing data for 2 values, including: [1, 2]
"""
if getattr(model, 'min_data_check', None) is None:
model.__num_min_data_checks = 0
Expand Down Expand Up @@ -331,43 +304,6 @@ def check_mandatory_components(model, *mandatory_model_components):
If an argument is a simple parameter, it must have a value.
This does not work with indexed sets.
EXAMPLE:
>>> from pyomo.environ import *
>>> import switch_model.utilities as utilities
>>> mod = ConcreteModel()
>>> mod.set_A = Set(initialize=[1,2])
>>> mod.paramA_full = Param(mod.set_A, initialize={1:'a',2:'b'})
>>> mod.paramA_empty = Param(mod.set_A)
>>> mod.set_B = Set()
>>> mod.paramB_empty = Param(mod.set_B)
>>> mod.paramC = Param(initialize=1)
>>> mod.paramD = Param()
>>> utilities.check_mandatory_components(mod, 'set_A', 'paramA_full')
True
>>> utilities.check_mandatory_components(mod, 'paramB_empty')
True
>>> utilities.check_mandatory_components(mod, 'paramC')
True
>>> utilities.check_mandatory_components(\
mod, 'set_A', 'paramA_empty') # doctest: +NORMALIZE_WHITESPACE
Traceback (most recent call last):
...
ValueError: Values are not provided for every element of the mandatory
parameter 'paramA_empty'. Missing data for 2 values, including: [1, 2]
>>> utilities.check_mandatory_components(mod, 'set_A', 'set_B')
Traceback (most recent call last):
...
ValueError: No data is defined for the mandatory set 'set_B'.
>>> utilities.check_mandatory_components(mod, 'paramC', 'paramD')
Traceback (most recent call last):
...
ValueError: Value not provided for mandatory parameter 'paramD'
# Demonstration of incorporating this function into Pyomo's BuildCheck()
>>> mod.min_dat_pass = BuildCheck(\
rule=lambda m: utilities.check_mandatory_components(\
m, 'set_A', 'paramA_full','paramB_empty', 'paramC'))
"""

for component_name in mandatory_model_components:
Expand Down
42 changes: 42 additions & 0 deletions tests/utilities_test.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Copyright 2015 The Switch Authors. All rights reserved.
# Licensed under the Apache License, Version 2, which is in the LICENSE file.

import logging
import os
import shutil
import tempfile
Expand Down Expand Up @@ -34,6 +35,47 @@ def test_save_inputs_as_dat(self):
finally:
shutil.rmtree(temp_dir)

def test_check_mandatory_components(self):
from pyomo.environ import ConcreteModel, Param, Set
from switch_model.utilities import check_mandatory_components
mod = ConcreteModel()
mod.set_A = Set(initialize=[1,2])
mod.paramA_full = Param(mod.set_A, initialize={1:'a',2:'b'})
mod.paramA_empty = Param(mod.set_A)
mod.set_B = Set()
mod.paramB_empty = Param(mod.set_B)
mod.paramC = Param(initialize=1)
mod.paramD = Param()
check_mandatory_components(mod, 'set_A', 'paramA_full')
check_mandatory_components(mod, 'paramB_empty')
check_mandatory_components(mod, 'paramC')
with self.assertRaises(ValueError):
check_mandatory_components(mod, 'set_A', 'paramA_empty')
with self.assertRaises(ValueError):
check_mandatory_components(mod, 'set_A', 'set_B')
with self.assertRaises(ValueError):
check_mandatory_components(mod, 'paramC', 'paramD')


def test_min_data_check(self):
from switch_model.utilities import _add_min_data_check
from pyomo.environ import AbstractModel, Param, Set
mod = AbstractModel()
_add_min_data_check(mod)
mod.set_A = Set(initialize=[1,2])
mod.paramA_full = Param(mod.set_A, initialize={1:'a',2:'b'})
mod.paramA_empty = Param(mod.set_A)
mod.min_data_check('set_A', 'paramA_full')
self.assertIsNotNone(mod.create_instance())
mod.min_data_check('set_A', 'paramA_empty')
# Fiddle with the pyomo logger to suppress its error message
logger = logging.getLogger('pyomo.core')
orig_log_level = logger.level
logger.setLevel(logging.FATAL)
with self.assertRaises(ValueError):
mod.create_instance()
logger.setLevel(orig_log_level)


if __name__ == '__main__':
unittest.main()

0 comments on commit 968c98e

Please sign in to comment.