Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update from @aliebman #1

Open
wants to merge 30 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8b01cda
flake8 fixes.
bje- Apr 8, 2019
ba95d55
[fix] Consistent pandas formatted output
jotaigna Apr 8, 2019
28835da
[fix] consistent output for emissions in statistics report
jotaigna Apr 8, 2019
a7f5954
[fix] json entries parsed more robustly
jotaigna Apr 8, 2019
db7a8f2
[feature] Added requirements file (thanks to Joel Courtney)
jotaigna Apr 8, 2019
09c428d
[fix]test_multi.py: do not save temp files in local directory
jotaigna Apr 8, 2019
ff58eac
* ssolve.py: Remove bare exception handler. Given that this code just
bje- Apr 8, 2019
9e6c229
Merge pull request #4 from bje-/master
jotaigna Apr 8, 2019
f01fdef
* msolve.py: Elimiate Pylint warning: W0108(unnecessary-lambda),
bje- Apr 8, 2019
d1fb8b0
* msolve.py: Eliminate Pylint warning W0612(unused-variable),
bje- Apr 8, 2019
5ecf5b8
* multi.py: Fix Pylint warning [R1716(chained-comparison), roundup]
bje- Apr 8, 2019
3b20b2b
* cemo/utils.py: Silence Pylint warning W0102: Dangerous default value
bje- Apr 8, 2019
ca20fa0
* cemo/cluster.py: Silence Pylint warning W0102: Dangerous default
bje- Apr 8, 2019
726baba
* cemo/const.py: Typo fix in a comment.
bje- Apr 8, 2019
736bac2
* cemo/utils.py: Elimiate Pylint warning: W0108(unnecessary-lambda),
bje- Apr 8, 2019
2796752
* cemo/jsonify.py: Rename 'input' to 'inp' to avoid a name clash with
bje- Apr 8, 2019
0a1f2ec
* cemo/const.py: Clean up broken expression.
bje- Apr 8, 2019
966e26a
* cemo/cluster.py: Rename 'max' to 'max_p' to avoid a name clash with
bje- Apr 8, 2019
4b62327
* cemo/rules.py: Silence Pylint warning R1705 (no-else-return)
bje- Apr 8, 2019
8b17781
* cemo/utils.py: Silence Pylint warning W0612(unused-variable),
bje- Apr 8, 2019
dba69ea
The expression 'True if expr else False' can be reduced to 'expr'.
bje- Apr 8, 2019
88a93f8
* tests/test_utils.py (test_printstats): Simplify.
bje- Apr 8, 2019
6d8d477
* cemo/utils.py: Whitespace fix.
bje- Apr 8, 2019
83e0423
* tets/test_utils.py: Use 'with' for automatic file closure.
bje- Apr 8, 2019
1624c26
Merge pull request #5 from bje-/master
jotaigna Apr 8, 2019
24508e6
tests/test_base.py Added docstrings
jotaigna Apr 9, 2019
ad2930b
test/test_multi.py Added docstrings
jotaigna Apr 9, 2019
256a88a
tests/test_jsonify.py Added docstrings
jotaigna Apr 9, 2019
53da2a8
test/test_rules.py Added docstrings
jotaigna Apr 11, 2019
d03282a
cemo/initialisers.py Added docstrings
jotaigna Apr 11, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions cemo/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ def __init__(self,
firstdow=4,
lastdow=3,
max_d=12,
regions=[1, 2, 3, 4, 5],
regions=None,
maxsynth=False):
self.firstdow = firstdow # Day of week starting period
self.lastdow = lastdow # Day of week ending period`
self.max_d = max_d # Maximum number of clusters
self.regions = regions # NEM region tuple
self.regions = range(1, 6) if regions is None else regions # NEM region tuple
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Supports a default versus all.
Should this be range(1, 6) @aliebman to advise?

self.maxsynth = maxsynth

# make week pattern into a list
Expand Down Expand Up @@ -113,13 +113,13 @@ def _get_region_data(self, region):

return X1

def _calc_Xsynth(self, max=False):
def _calc_Xsynth(self, max_p=False):
# empty array of synthetic individual in each cluster
self.Xsynth = np.empty((self.max_d, self.nplen))

for k in range(self.max_d):
# calculate synthetic individual per clusters
if max:
if max_p:
self.Xsynth[k] = self.Xclus[k].max(axis=0)[:self.nplen]
else:
self.Xsynth[k] = self.Xclus[k].mean(axis=0)[:self.nplen]
Expand All @@ -140,7 +140,7 @@ def clusterset(self, max_d, method='average', metric='cityblock'):
self.Xclus[self.cluster[j] - 1] \
= np.row_stack((self.Xclus[self.cluster[j] - 1], X2[j, :]))
# genereate Xsynth (by default is the max of all features in cluster)
self._calc_Xsynth(max=self.maxsynth)
self._calc_Xsynth(max_p=self.maxsynth)

# Obtain the date index for the observation in each cluster
# closest to their respective cluster mean
Expand Down
5 changes: 2 additions & 3 deletions cemo/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
11: 20975.96,
12: 10487.98,
16: 52439.9,
19: 52439.9 # FIXME Sould this be 10k like for gas?
19: 52439.9 # FIXME Should this be 10k like for gas?
}

DEFAULT_TECH_LIFETIME = {
Expand Down Expand Up @@ -225,8 +225,7 @@
17: 0,
},
5: {
11: 4000 + 3000 + 1000 +
29.9, # Brkn hill + 1/2 of Murray R + 1/2 of Riverland + existing
11: 4000 + 3000 + 1000 + 29.9, # Brkn hill + 1/2 of Murray R + 1/2 of Riverland + existing
12: 1870 + 1620 + 232.5 + 0,
17: 620 + 527.5 + 77.5 + 199, #
},
Expand Down
33 changes: 31 additions & 2 deletions cemo/initialisers.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@


def init_year_correction_factor(model):
#pylint: disable=unused-argument
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, what argument is being ignored? o.O

'''Calculate factor to adjust dispatch periods different to 8760 hours'''
ystr = model.t.last()
year = int(ystr[:4])
Expand All @@ -23,81 +24,109 @@ def init_year_correction_factor(model):


def init_zones_in_regions(model):
#pylint: disable=unused-argument
'''Return zones in region tuples for declared regions'''
for i in cemo.const.ZONES_IN_REGIONS:
if i[0] in model.regions and i[1] in model.zones:
yield i


def init_region_intercons(model):
#pylint: disable=unused-argument
'''Return regional interconnectors for declared regions'''
for i in cemo.const.REGION_INTERCONS:
if i[0] in model.regions and i[1] in model.regions:
yield i


def init_stor_rt_eff(model, tech):
#pylint: disable=unused-argument
'''Default return efficiency for storage techs'''
return cemo.const.DEFAULT_STOR_PROPS["rt_eff"].get(tech, 0)


def init_stor_charge_hours(model, tech):
#pylint: disable=unused-argument
'''Default charge hours for storage tech'''
return cemo.const.DEFAULT_STOR_PROPS["charge_hours"].get(tech, 0)


def init_hyb_col_mult(model, tech):
#pylint: disable=unused-argument
'''Default collector multiple for hybrid tech'''
return cemo.const.DEFAULT_HYB_PROPS["col_mult"].get(tech, 0)


def init_hyb_charge_hours(model, tech):
#pylint: disable=unused-argument
'''Default charge hours for hybrid tech'''
return cemo.const.DEFAULT_HYB_PROPS["charge_hours"].get(tech, 0)


def init_intercon_prop_factor(m, source, dest):
def init_intercon_prop_factor(model, source, dest):
#pylint: disable=unused-argument
'''Initialise interconnector proportioning factors'''
return cemo.const.INTERCON_PROP_FACTOR.get(source).get(dest, 0)


def init_intercon_trans_limit(m, source, dest):
def init_intercon_trans_limit(model, source, dest):
#pylint: disable=unused-argument
'''Initialise interconecto transmission limits'''
return cemo.const.INTERCON_TRANS_LIMIT.get(source).get(dest)


def init_default_fuel_price(model, zone, tech):
#pylint: disable=unused-argument
'''Assign default price across zone and technologies'''
return cemo.const.DEFAULT_FUEL_PRICE.get(tech, 100.0)


def init_default_heat_rate(model, zone, tech):
#pylint: disable=unused-argument
'''Initialise default heat rate for fuel based generators in each zone'''
return cemo.const.DEFAULT_HEAT_RATE.get(tech, 15.0)


def init_default_fuel_emit_rate(model, tech):
#pylint: disable=unused-argument
'''Default fuel emission rate for fuel based generators'''
return cemo.const.DEFAULT_FUEL_EMIT_RATE.get(tech, 800)


def init_cost_retire(model, tech):
#pylint: disable=unused-argument
'''Default retirement/rehabilitation cost in $/MW per technology'''
return cemo.const.DEFAULT_RETIREMENT_COST.get(tech, 60000.0)


def init_default_lifetime(model, tech):
#pylint: disable=unused-argument
'''Default lifetime for technologies'''
return cemo.const.DEFAULT_TECH_LIFETIME.get(tech, 30.0)


def init_gen_build_limit(model, zone, tech):
#pylint: disable=unused-argument
''' Default build limits per technology and per zone'''
return cemo.const.DEFAULT_BUILD_LIMIT.get(zone).get(tech, 100000)


def init_fcr(model, tech):
#pylint: disable=unused-argument
'''Calculate fixed charge rate for each technology'''
return model.all_tech_discount_rate / (
(model.all_tech_discount_rate + 1)**model.all_tech_lifetime[tech] -
1) + model.all_tech_discount_rate


def init_cap_factor(model, zone, tech, time):
#pylint: disable=unused-argument
'''Default capacity factor per hour per technology and per zone.
Note:Default to zero means technology does not generate'''
return cemo.const.GEN_CAP_FACTOR.get(tech, 0)


def init_max_hydro(model, zone):
#pylint: disable=unused-argument
'''Default maximum hydro generation per year in each zone'''
return cemo.const.DEFAULT_HYDRO_MWH_MAX.get(zone, 0)
6 changes: 3 additions & 3 deletions cemo/jsonify.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,10 @@ def jsonify(inst):

def jsoninit(inst):
'''Produce JSON output sufficient to initialise a cemo model'''
input = jsonify(inst)
inp = jsonify(inst)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why truncate?

out = {}
out.update(input['sets'])
out.update(input['params'])
out.update(inp['sets'])
out.update(inp['params'])

del out['zones_per_region']
del out['gen_tech_per_zone']
Expand Down
23 changes: 14 additions & 9 deletions cemo/multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def roundup(cap):
Catching small negative numbers due to solver numerical tolerance.
Let big negative numners pass to raise exception.
'''
if cap > -1e-6 and cap < 0:
if -1e-6 < cap < 0:
return 0
return round(cap, 2)

Expand Down Expand Up @@ -119,12 +119,12 @@ def __init__(self, cfgfile, solver='cbc', log=False, tmpdir=tempfile.mkdtemp() +
self.nem_re_disp_ratio = json.loads(Scenario['nem_re_disp_ratio'])
# Keep track of policy options to configure model instances down the line
self.model_options = {
'nem_ret_ratio': (True if self.nem_ret_ratio is not None else False),
'nem_ret_gwh': (True if self.nem_ret_gwh is not None else False),
'region_ret_ratio': (True if self.region_ret_ratio is not None else False),
'emitlimit': (True if self.emitlimit is not None else False),
'nem_disp_ratio': (True if self.nem_disp_ratio is not None else False),
'nem_re_disp_ratio': (True if self.nem_re_disp_ratio is not None else False),
'nem_ret_ratio': self.nem_ret_ratio is not None,
'nem_ret_gwh': self.nem_ret_gwh is not None,
'region_ret_ratio': self.region_ret_ratio is not None,
'emitlimit': self.emitlimit is not None,
'nem_disp_ratio': self.nem_disp_ratio is not None,
'nem_re_disp_ratio': self.nem_re_disp_ratio is not None
}

self.discountrate = Scenario['discountrate']
Expand Down Expand Up @@ -339,7 +339,7 @@ def exogenous_capacity(self, a):

def tracetechs(self): # TODO refactor this and how tech sets populate template
self.fueltech = {}
self.committech ={}
self.committech = {}
self.regentech = {}
self.dispgentech = {}
self.redispgentech = {}
Expand Down Expand Up @@ -496,7 +496,12 @@ def produce_exogenous_capacity(self, year):
exogenous_capacity += '#Exogenous capacity entry ' + key + '\n'
exogenous_capacity += 'param ' + key + ':=\n'
exogenous_capacity += cap[['zone', 'tech', 'value']
].to_string(header=False, index=False)
].to_string(header=False, index=False,
formatters={
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make the formatter a constant?

'zone': lambda x: '%i' % x,
'tech': lambda x: '%i' % x,
'value': lambda x: '%10.2f' % x,
})
exogenous_capacity += '\n;\n'

return exogenous_capacity
Expand Down
17 changes: 8 additions & 9 deletions cemo/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,16 +338,15 @@ def con_opcap(model, z, n): # z and n come both from TechinZones
return model.gen_cap_op[z, n] == model.gen_cap_initial[z, n] \
+ (model.gen_cap_exo[z, n] - model.gen_cap_exo_neg[z, n])

else:
if n in model.retire_gen_tech:
return model.gen_cap_op[z, n] == model.gen_cap_initial[z, n] \
+ (model.gen_cap_exo[z, n] - model.gen_cap_exo_neg[z, n])\
+ model.gen_cap_new[z, n]\
- model.gen_cap_ret[z, n] - \
(model.ret_gen_cap_exo[z, n] - model.gen_cap_ret_neg[z, n])
return model.gen_cap_op[z, n] == model.gen_cap_initial[z, n]\
if n in model.retire_gen_tech:
return model.gen_cap_op[z, n] == model.gen_cap_initial[z, n] \
+ (model.gen_cap_exo[z, n] - model.gen_cap_exo_neg[z, n])\
+ model.gen_cap_new[z, n]
+ model.gen_cap_new[z, n]\
- model.gen_cap_ret[z, n] - \
(model.ret_gen_cap_exo[z, n] - model.gen_cap_ret_neg[z, n])
return model.gen_cap_op[z, n] == model.gen_cap_initial[z, n]\
+ (model.gen_cap_exo[z, n] - model.gen_cap_exo_neg[z, n])\
+ model.gen_cap_new[z, n]


def con_stcap(model, z, s): # z and n come both from TechinZones
Expand Down
14 changes: 9 additions & 5 deletions cemo/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def _techsinregion(instance, region): # pragma: no cover
techsinregion = techsinregion | instance.gen_tech_per_zone[z]()
techsinregion = techsinregion | instance.hyb_tech_per_zone[z]()
techsinregion = techsinregion | instance.stor_tech_per_zone[z]()
return sorted(techsinregion, key=lambda x: cemo.const.DISPLAY_ORDER.index(x))
return sorted(techsinregion, key=cemo.const.DISPLAY_ORDER.index)


def palette(instance, techsinregion): # pragma: no cover
Expand Down Expand Up @@ -211,7 +211,7 @@ def _printemissionrate(instance):
emrate = sum(value(cemo.rules.emissions(instance, r))
for r in instance.regions) /\
(sum(value(cemo.rules.dispatch(instance, r)) for r in instance.regions)+1.0e-12)
print("Total Emission rate: %s kg/MWh" % str(emrate))
print("Total Emission rate: %6.3f kg/MWh" % emrate)


def _printunserved(instance):
Expand Down Expand Up @@ -281,11 +281,11 @@ def printstats(instance):
print("End of results for %s" % instance.name, flush=True)


def plotcluster(cluster, row=3, col=4, ylim=[5500, 16000]): # pragma: no cover
def plotcluster(cluster, row=3, col=4, ylim=None): # pragma: no cover
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps use a more common default value method?

Also, what is 5500 and 16000?

# Plot cluster result from full set of weeks, cluster weeks and weights
t = range(1, cluster.nplen + 1)
# Make row * col subplots
f, axarr = plt.subplots(row, col, sharex=True)
axarr = plt.subplots(row, col, sharex=True)[1]
# Plot each observation in their respective cluster plot
for i in range(cluster.periods):
axarr.flat[cluster.cluster[i] -
Expand All @@ -302,6 +302,10 @@ def plotcluster(cluster, row=3, col=4, ylim=[5500, 16000]): # pragma: no cover
marker='+') # closest observation
# make yrange the same in all plots
for ax in axarr.flat:
ax.set_ylim(ylim[0], ylim[1])
if ylim is None:
# default
ax.set_ylim(5500, 16000)
else:
ax.set_ylim(ylim[0], ylim[1])
# Show results
plt.show(figsize=(14, 9))
7 changes: 3 additions & 4 deletions msolve.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@


def valid_file(param):
base, ext = os.path.splitext(param)
ext = os.path.splitext(param)[1]
if ext not in ('.cfg'):
raise argparse.ArgumentTypeError('File must have a cfg extension')
return param
Expand All @@ -35,7 +35,7 @@ def valid_file(param):
"config",
help="Specify a configuration file for simulation" +
" Note: Python configuration files named CONFIG.cfg",
type=lambda f: valid_file(f),
type=valid_file,
metavar='CONFIG')
# Obtain a solver name from command line, default cbc
parser.add_argument(
Expand All @@ -55,8 +55,7 @@ def valid_file(param):
parser.add_argument(
"-k",
"--keepfiles",
help=
"Save generated files onto a folder with the same name as the configuration file",
help="Save generated files onto a folder with the same name as the configuration file",
action='store_true')

# parse arguments into args structure
Expand Down
23 changes: 23 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
appdirs==1.4.3
atomicwrites==1.3.0
attrs==19.1.0
cycler==0.10.0
kiwisolver==1.0.1
matplotlib==3.0.3
more-itertools==7.0.0
nose==1.3.7
numpy==1.16.2
pandas==0.24.2
pluggy==0.9.0
ply==3.11
py==1.8.0
PyMySQL==0.9.3
Pyomo==5.6.1
pyparsing==2.3.1
pytest==4.4.0
python-dateutil==2.8.0
pytz==2018.9
PyUtilib==5.6.5
scipy==1.2.1
si-prefix==1.2.2
six==1.12.0
6 changes: 1 addition & 5 deletions ssolve.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,7 @@ def check_arg(config_file, parameter):
region_ret_ratio=check_arg(MODEL_NAME, 'region_ret_ratio'),
nem_re_disp_ratio=check_arg(MODEL_NAME, 'nem_re_disp_ratio'))
# create a specific instance using file modelName.dat
try:
INSTANCE = MODEL.create_instance(MODEL_NAME + '.dat')
except Exception as ex:
print("openCEM solve.py: ", ex)
sys.exit(1) # exit gracefully if file does not exist
INSTANCE = MODEL.create_instance(MODEL_NAME + '.dat')

# Produce only a debugging printout of model and then exit
if ARGS.printonly:
Expand Down
2 changes: 1 addition & 1 deletion tests/Sim2020.dat
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,7 @@ order BY regions,t;": [regions,t] region_net_demand;
#Custom cost entry for cost_stor_build
param cost_stor_build:=
13 14 999999.00
5 21 2000000.00
5 21 2000000.00
;
#Custom cost entry for cost_gen_fom
param cost_gen_fom:=
Expand Down
Loading