Skip to content

Commit 0b6e2ba

Browse files
committed
Fix issues from v1 rebase
Update fuel split calculations in ecm_prep to correctly reflect changes to account for dual fuel measures (commit 130c2d1). Remove superfluous updating of efficient-captured fuel splits data in ecm_prep, which effectively repeated those calculations multiple times. Reapply exogenous heating rates to secondary heating as well in ecm_prep. In run, reintroduce stock cost reporting that was erroneously removed, and add the more robust handling of zero/blank fuel split adjustments from commit c8a21e6.
1 parent 4ba3af0 commit 0b6e2ba

File tree

2 files changed

+137
-53
lines changed

2 files changed

+137
-53
lines changed

scout/ecm_prep.py

Lines changed: 13 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4216,8 +4216,8 @@ def fill_mkts(self, msegs, msegs_cpl, convert_data, tsv_data_init, opts,
42164216
no_stk_mseg = ""
42174217

42184218
# Flag whether exogenous HP rates apply to current mseg.
4219-
# Assume only heating, water heating, and cooking end uses are
4220-
# covered by these exogenous rates (no secondary heating); do
4219+
# Assume only heating, secondary heating, water heating, and cooking
4220+
# end uses are covered by these exogenous rates; do
42214221
# not apply rates to wood stoves; and ensure that these rates
42224222
# are only assessed for equipment microsegments (e.g., they do
42234223
# not apply to envelope component heating energy msegs); are
@@ -4230,7 +4230,7 @@ def fill_mkts(self, msegs, msegs_cpl, convert_data, tsv_data_init, opts,
42304230
("stove (wood)" not in self.technology["primary"]) and \
42314231
(mskeys[-2] is None or "HP" not in mskeys[-2]) and (any([
42324232
x in mskeys for x in [
4233-
"heating", "water heating", "cooking"]]) or (
4233+
"heating", "secondary heating", "water heating", "cooking"]]) or (
42344234
self.linked_htcl_tover and
42354235
self.linked_htcl_tover_anchor_eu == "heating")):
42364236
hp_rate_flag = True
@@ -12015,12 +12015,13 @@ def add_sectshape_energy(self, cm, sect_shape_init, add_energy,
1201512015
# Add energy data for current mseg, subtracting out any efficient-
1201612016
# case energy that remains with fossil fuel (not applicable to
1201712017
# sector shapes)
12018-
((add_energy[s][yr] * (1 - (fs_eff_splt_energy[0][yr] /
12019-
fs_eff_splt_energy[1][yr]))
12018+
((add_energy[s][yr] * (1 - (
12019+
(fs_eff_splt_energy[0][yr] + fs_eff_splt_energy[1][yr]) /
12020+
fs_eff_splt_energy[2][yr]))
1202012021
# Pull in fuel split as needed
1202112022
if (fs_eff_splt_energy and s == "efficient" and
1202212023
"electricity" not in cm
12023-
and fs_eff_splt_energy[1][yr] != 0)
12024+
and fs_eff_splt_energy[2][yr] != 0)
1202412025
else add_energy[s][yr])
1202512026
# Only add energy data to sector shapes if data concerns
1202612027
# electricity mseg or fuel switching from fossil is occurring and
@@ -13458,7 +13459,8 @@ def find_adj_out_break_cats(
1345813459
out_cz][out_bldg][out_eu][out_fuel_gain] = {
1345913460
yr: mseg_out_break_adj[k]["efficient-captured"][
1346013461
out_cz][out_bldg][out_eu][out_fuel_gain][yr] - (
13461-
eff_capt_orig[yr] - eff_capt_adj[yr])
13462+
eff_capt_orig[yr] - eff_capt_adj[yr]) * (
13463+
1 - fs_eff_splt_var_capt[yr])
1346213464
for yr in self.handyvars.aeo_years}
1346313465
# Update efficient captured for envelope portion of pkg. if
1346413466
# this is being tracked
@@ -13480,24 +13482,16 @@ def find_adj_out_break_cats(
1348013482
eff_orig[yr] - eff_adj[yr]) * (
1348113483
1 - fs_eff_splt_var[yr]))
1348213484
for yr in self.handyvars.aeo_years}
13483-
# Measure-captured efficient energy for switched to fuel
13484-
# (if reported)
13485-
if eff_capt:
13486-
mseg_out_break_adj[k]["efficient-captured"][
13487-
out_cz][out_bldg][out_eu][out_fuel_gain] = {
13488-
yr: mseg_out_break_adj[k]["efficient-captured"][
13489-
out_cz][out_bldg][out_eu][out_fuel_gain][yr] - (
13490-
eff_capt_orig[yr] - eff_capt_adj[yr])
13491-
for yr in self.handyvars.aeo_years}
1349213485
# Energy costs
1349313486
if all([x for x in [tot_base_orig_ecost, tot_eff_orig_ecost,
1349413487
tot_save_orig_ecost]]):
1349513488
# Pull the fraction of efficient-case energy cost that remains
1349613489
# w/ the orig. fuel in each year for the contrib. measure/mseg
1349713490
fs_eff_splt_cost = {
13498-
yr: (fs_eff_splt["cost"][0][yr] /
13499-
fs_eff_splt["cost"][1][yr]) if
13500-
fs_eff_splt["cost"][1][yr] != 0 else 1
13491+
yr: ((fs_eff_splt["cost"][0][yr] +
13492+
fs_eff_splt["cost"][1][yr]) /
13493+
fs_eff_splt["cost"][2][yr]) if
13494+
fs_eff_splt["cost"][2][yr] != 0 else 1
1350113495
for yr in self.handyvars.aeo_years}
1350213496

1350313497
# Energy cost; original fuel
@@ -13593,15 +13587,6 @@ def find_adj_out_break_cats(
1359313587
out_cz][out_bldg][out_eu][out_fuel_save][yr] - (
1359413588
save_orig[yr] - (base_adj[yr] - eff_adj[yr])) for
1359513589
yr in self.handyvars.aeo_years}
13596-
# Measure-captured efficient energy (if reported)
13597-
if eff_capt:
13598-
# Remove adjusted efficient
13599-
mseg_out_break_adj[k]["efficient-captured"][
13600-
out_cz][out_bldg][out_eu][out_fuel_save] = {
13601-
yr: mseg_out_break_adj[k]["efficient-captured"][
13602-
out_cz][out_bldg][out_eu][out_fuel_save][yr] - (
13603-
eff_capt_orig[yr] - eff_capt_adj[yr]) for
13604-
yr in self.handyvars.aeo_years}
1360513590

1360613591
# Energy costs
1360713592
if all([x for x in [tot_base_orig_ecost, tot_eff_orig_ecost,
@@ -13671,14 +13656,6 @@ def find_adj_out_break_cats(
1367113656
out_cz][out_bldg][out_eu][yr] - (
1367213657
save_orig[yr] - (base_adj[yr] - eff_adj[yr])) for
1367313658
yr in self.handyvars.aeo_years}
13674-
# Measure-captured efficient energy (if reported)
13675-
if eff_capt:
13676-
mseg_out_break_adj[k][
13677-
"efficient-captured"][out_cz][out_bldg][out_eu] = {
13678-
yr: mseg_out_break_adj[k]["efficient-captured"][
13679-
out_cz][out_bldg][out_eu][yr] - (
13680-
eff_capt_orig[yr] - eff_capt_adj[yr]) for
13681-
yr in self.handyvars.aeo_years}
1368213659

1368313660
# Energy costs
1368413661
if all([x for x in [tot_base_orig_ecost, tot_eff_orig_ecost,

scout/run.py

Lines changed: 124 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2640,16 +2640,26 @@ def htcl_adj(self, measures_htcl_adj, adopt_scheme, htcl_adj_data):
26402640
"total"][var_sub][yr]) * (
26412641
1 - adj_frac_t) * fs_eff_splt_var
26422642
else:
2643-
# Handle efficient-captured energy case for
2644-
# fuel switching, where no base fuel data will
2645-
# be reported (go to next variable in loop)
2643+
# Handle case where no base fuel data is reported, which is
2644+
# conceivable for fuel switching (go to next variable in loop)
26462645
try:
2647-
adj_out_break[
2648-
"base fuel"][var][var_sub][yr] = \
2649-
adj_out_break["base fuel"][var][
2650-
var_sub][yr] - (
2651-
adj[var]["total"][var_sub][yr]) * (
2652-
1 - adj_frac_t) * fs_eff_splt_var
2646+
# Ensure baseline result is not already zero before
2647+
# adjusting; if zero, no further adjustment required
2648+
if (not isinstance(
2649+
adj_out_break["base fuel"][var][var_sub][yr], numpy.ndarray)
2650+
and adj_out_break["base fuel"][var][var_sub][yr] != 0) or (
2651+
isinstance(
2652+
adj_out_break["base fuel"][var][var_sub][yr],
2653+
numpy.ndarray) and all(adj_out_break[
2654+
"base fuel"][var][var_sub][yr]) != 0):
2655+
adj_out_break[
2656+
"base fuel"][var][var_sub][yr] = \
2657+
adj_out_break["base fuel"][var][
2658+
var_sub][yr] - (
2659+
adj[var]["total"][var_sub][yr]) * (
2660+
1 - adj_frac_t) * fs_eff_splt_var
2661+
else:
2662+
continue
26532663
except KeyError:
26542664
continue
26552665

@@ -3862,15 +3872,23 @@ def compete_adj(
38623872
adj_key = "measure"
38633873
else:
38643874
adj_key = var_sub
3865-
# Handle efficient-captured energy case for fuel switching,
3866-
# where no base fuel data will be reported (skip to next
3867-
# variable)
3875+
# Handle case where no base fuel data is reported, which is conceivable
3876+
# for fuel switching (go to next variable in loop)
38683877
try:
3869-
adj_out_break["base fuel"][var][var_sub][yr] = \
3870-
adj_out_break["base fuel"][var][
3871-
var_sub][yr] - (
3872-
adj[var]["total"][adj_key][yr]) * (
3873-
1 - adj_t) * fs_eff_splt_var
3878+
# Ensure baseline result is not already zero before adjusting; if zero, no
3879+
# further adjustment required
3880+
if (not isinstance(
3881+
adj_out_break["base fuel"][var][var_sub][yr], numpy.ndarray)
3882+
and adj_out_break["base fuel"][var][var_sub][yr] != 0) or (
3883+
isinstance(adj_out_break["base fuel"][var][var_sub][yr], numpy.ndarray)
3884+
and all(adj_out_break["base fuel"][var][var_sub][yr]) != 0):
3885+
adj_out_break["base fuel"][var][var_sub][yr] = \
3886+
adj_out_break["base fuel"][var][
3887+
var_sub][yr] - (
3888+
adj[var]["total"][adj_key][yr]) * (
3889+
1 - adj_t) * fs_eff_splt_var
3890+
else:
3891+
continue
38743892
except KeyError:
38753893
continue
38763894

@@ -4995,6 +5013,95 @@ def finalize_outputs(
49955013
# the dict with these is calculated above
49965014
self.output_ecms[m.name]["Markets and Savings (by Category)"][
49975015
adopt_scheme]["Stock Penetration (%)"] = frac_mkt_stk
5016+
# If a user desires stock data as an output, calculate and report
5017+
# these data for the baseline and measure cases
5018+
if self.opts.report_stk is True:
5019+
# Set baseline and measure stock keys, including units that
5020+
# are calculated above
5021+
base_stk_uc_key, base_stk_c_key, meas_stk_key = [
5022+
x + stk_units for x in [
5023+
"Baseline Stock (Uncompeted)",
5024+
"Baseline Stock (Competed)",
5025+
"Measure Stock (Competed)"]]
5026+
# Report baseline stock and stock cost figures (all baseline
5027+
# stock/stock cost that the measure could affect/capture);
5028+
# report both uncompeted/competed versions
5029+
stk_base_uc = {yr: m.markets[adopt_scheme][
5030+
"uncompeted"]["master_mseg"]["stock"][
5031+
"total"]["all"][yr] for yr in focus_yrs}
5032+
stk_base_c = {
5033+
yr: mkts["stock"]["total"]["all"][yr] for yr in focus_yrs}
5034+
stk_cost_base = {yr: mkts["cost"]["stock"]["total"][
5035+
"baseline"][yr] for yr in focus_yrs}
5036+
self.output_ecms[m.name]["Markets and Savings (Overall)"][
5037+
adopt_scheme][base_stk_uc_key] = stk_base_uc
5038+
self.output_ecms[m.name]["Markets and Savings (Overall)"][
5039+
adopt_scheme][base_stk_c_key] = stk_base_c
5040+
# Report measure stock and stock cost figures
5041+
stk_meas, stk_cost_meas = [{yr: mkts["stock"]["total"][
5042+
"measure"][yr] for yr in focus_yrs},
5043+
{yr: mkts["cost"]["stock"]["total"][
5044+
"efficient"][yr] for yr in focus_yrs}]
5045+
# Calculate average and low/high measure stock and stock
5046+
# cost figures
5047+
stk_meas_avg, stk_cost_meas_avg = [{
5048+
k: numpy.mean(v) for k, v in sv.items()} for sv in [
5049+
stk_meas, stk_cost_meas]]
5050+
stk_meas_low, stk_cost_meas_low = [{
5051+
k: numpy.percentile(v, 5) for k, v in sv.items()} for sv
5052+
in [stk_meas, stk_cost_meas]]
5053+
stk_meas_high, stk_cost_meas_high = [{
5054+
k: numpy.percentile(v, 95) for k, v in stk_meas.items()}
5055+
for sv in [stk_meas, stk_cost_meas]]
5056+
# Set the average measure stock output
5057+
self.output_ecms[m.name]["Markets and Savings (Overall)"][
5058+
adopt_scheme][meas_stk_key] = stk_meas_avg
5059+
# Set the average measure stock cost output
5060+
self.output_ecms[m.name]["Markets and Savings (Overall)"][
5061+
adopt_scheme][stk_cost_key_tot] = stk_cost_meas_avg
5062+
# Set the average measure incremental stock cost output
5063+
self.output_ecms[m.name]["Markets and Savings (Overall)"][
5064+
adopt_scheme][stk_cost_key_inc] = {
5065+
yr: (stk_cost_meas_avg[yr] - stk_cost_base[yr])
5066+
for yr in focus_yrs}
5067+
# Update stock cost data across all ECMs with data for
5068+
# current ECM
5069+
for yr in focus_yrs:
5070+
# Add to total stock cost data (first element of list)
5071+
stk_cost_all_ecms[0][yr] += stk_cost_meas_avg[yr]
5072+
# Add to inc. stock cost data (second element of list)
5073+
stk_cost_all_ecms[1][yr] += (
5074+
stk_cost_meas_avg[yr] - stk_cost_base[yr])
5075+
# Set low/high measure stock outputs (as applicable)
5076+
if stk_meas_avg != stk_meas_low:
5077+
meas_stk_key_low, stk_cost_key_tot_low, \
5078+
stk_cost_key_inc_low = [x + " (low)" for x in [
5079+
meas_stk_key, stk_cost_key_tot, stk_cost_key_inc]]
5080+
meas_stk_key_high, stk_cost_key_tot_high, \
5081+
stk_cost_key_inc_high = [x + " (high)" for x in [
5082+
meas_stk_key, stk_cost_key_tot, stk_cost_key_inc]]
5083+
self.output_ecms[m.name]["Markets and Savings (Overall)"][
5084+
adopt_scheme][meas_stk_key_low] = stk_meas_low
5085+
self.output_ecms[m.name]["Markets and Savings (Overall)"][
5086+
adopt_scheme][meas_stk_key_high] = stk_meas_high
5087+
# Set the low measure stock cost output
5088+
self.output_ecms[m.name]["Markets and Savings (Overall)"][
5089+
adopt_scheme][stk_cost_key_tot_low] = \
5090+
stk_meas_low
5091+
# Set the low measure incremental stock cost output
5092+
self.output_ecms[m.name]["Markets and Savings (Overall)"][
5093+
adopt_scheme][stk_cost_key_inc_low] = {
5094+
yr: (stk_cost_meas_low[yr] - stk_cost_base[yr])
5095+
for yr in focus_yrs}
5096+
# Set the high measure stock cost output
5097+
self.output_ecms[m.name]["Markets and Savings (Overall)"][
5098+
adopt_scheme][stk_cost_key_tot_high] = \
5099+
stk_cost_meas_high
5100+
# Set the high measure incremental stock cost output
5101+
self.output_ecms[m.name]["Markets and Savings (Overall)"][
5102+
adopt_scheme][stk_cost_key_inc_high] = {
5103+
yr: (stk_cost_meas_high[yr] - stk_meas_high[yr])
5104+
for yr in focus_yrs}
49985105

49995106
# If a user desires output compatible with GCAM format, assess
50005107
# impacts of measures on GCAM baselines stock/energy segments.

0 commit comments

Comments
 (0)