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

Fix rollover issues in bill w/o system #941

Merged
merged 1 commit into from Nov 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
52 changes: 31 additions & 21 deletions ssc/cmod_utilityrate5.cpp
Expand Up @@ -593,7 +593,9 @@ class cm_utilityrate5 : public compute_module
monthly_salespurchases(12),
monthly_load(12), monthly_system_generation(12), monthly_elec_to_grid(12),
monthly_elec_needed_from_grid(12),
monthly_cumulative_excess_energy(12), monthly_cumulative_excess_dollars(12), monthly_bill(12), monthly_test(12),
monthly_cumulative_excess_energy_w_sys(12), monthly_cumulative_excess_dollars_w_sys(12),
monthly_cumulative_excess_energy_wo_sys(12), monthly_cumulative_excess_dollars_wo_sys(12),
monthly_bill(12), monthly_test(12),
monthly_two_meter_sales(12),
monthly_peak_wo_sys(12), monthly_peak_w_sys(12), // can't re-use these due to their role in billing demand
monthly_true_up_credits(12), // Realistically only one true-up month will be non-zero, but track them all for monthly outputs
Expand Down Expand Up @@ -876,18 +878,24 @@ class cm_utilityrate5 : public compute_module



ur_month last_month;
ssc_number_t last_excess_energy = 0;
ssc_number_t last_excess_dollars = 0;

ur_month last_month_wo_sys;
ssc_number_t last_excess_energy_wo_sys = 0;
ssc_number_t last_excess_dollars_wo_sys = 0;
ur_month last_month_w_sys;
ssc_number_t last_excess_energy_w_sys = 0;
ssc_number_t last_excess_dollars_w_sys = 0;

idx = 0;
for (i=0;i<nyears;i++)
{
if (i > 0) {
last_month = rate.m_month[11];
last_excess_energy = monthly_cumulative_excess_energy[11];
last_excess_dollars = monthly_cumulative_excess_dollars[11];
last_month_w_sys = rate.m_month[11];
last_excess_energy_w_sys = monthly_cumulative_excess_energy_w_sys[11];
last_excess_dollars_w_sys = monthly_cumulative_excess_dollars_w_sys[11];

// last_month_wo_sys set below
last_excess_energy_wo_sys = monthly_cumulative_excess_energy_wo_sys[11];
last_excess_dollars_wo_sys = monthly_cumulative_excess_dollars_wo_sys[11];
}
for (j = 0; j<m_num_rec_yearly; j++)
{
Expand Down Expand Up @@ -958,13 +966,13 @@ class cm_utilityrate5 : public compute_module
&monthly_excess_dollars_earned[0],
&monthly_excess_kwhs_earned[0],
&monthly_net_billing_credits[0],
&rate.dc_hourly_peak[0], &monthly_cumulative_excess_energy[0],
&monthly_cumulative_excess_dollars[0], &monthly_bill[0],
&rate.dc_hourly_peak[0], &monthly_cumulative_excess_energy_wo_sys[0],
&monthly_cumulative_excess_dollars_wo_sys[0], &monthly_bill[0],
&monthly_two_meter_sales[0],
&monthly_true_up_credits[0],
&monthly_billing_demand_peaks_wo_sys[0],
rate.rate_scale[i], i,
last_excess_dollars);
last_excess_dollars_wo_sys);
}
else
{
Expand All @@ -976,14 +984,16 @@ class cm_utilityrate5 : public compute_module
&monthly_excess_dollars_earned[0],
&monthly_nm_dollars_applied[0],
&monthly_excess_kwhs_earned[0],
&rate.dc_hourly_peak[0], &monthly_cumulative_excess_energy[0],
&monthly_cumulative_excess_dollars[0], &monthly_bill[0],
&rate.dc_hourly_peak[0], &monthly_cumulative_excess_energy_wo_sys[0],
&monthly_cumulative_excess_dollars_wo_sys[0], &monthly_bill[0],
&monthly_true_up_credits[0],
&monthly_billing_demand_peaks_wo_sys[0],
rate.rate_scale[i], i,
&last_month, last_excess_energy, last_excess_dollars);
&last_month_wo_sys, last_excess_energy_wo_sys, last_excess_dollars_wo_sys);
}

last_month_wo_sys = ur_month(rate.m_month[11]); // Deep copy now so it's available next y

for (j = 0; j < 12; j++)
{
utility_bill_wo_sys_ym[(i + 1) * 12 + j] = monthly_bill[j];
Expand Down Expand Up @@ -1137,11 +1147,11 @@ class cm_utilityrate5 : public compute_module
&monthly_excess_dollars_earned[0],
&monthly_excess_kwhs_earned[0],
&monthly_net_billing_credits[0],
&rate.dc_hourly_peak[0], &monthly_cumulative_excess_energy[0], &monthly_cumulative_excess_dollars[0], &monthly_bill[0],
&rate.dc_hourly_peak[0], &monthly_cumulative_excess_energy_w_sys[0], &monthly_cumulative_excess_dollars_w_sys[0], &monthly_bill[0],
&monthly_two_meter_sales[0], &monthly_true_up_credits[0],
&monthly_billing_demand_peaks_w_sys[0],
rate.rate_scale[i],
i, last_excess_dollars, false, false, true);
i, last_excess_dollars_w_sys, false, false, true);
}
else
{
Expand All @@ -1154,11 +1164,11 @@ class cm_utilityrate5 : public compute_module
&monthly_excess_dollars_earned[0],
&monthly_excess_kwhs_earned[0],
&monthly_net_billing_credits[0],
&rate.dc_hourly_peak[0], &monthly_cumulative_excess_energy[0], &monthly_cumulative_excess_dollars[0],
&rate.dc_hourly_peak[0], &monthly_cumulative_excess_energy_w_sys[0], &monthly_cumulative_excess_dollars_w_sys[0],
&monthly_bill[0], &monthly_two_meter_sales[0],
&monthly_true_up_credits[0],
&monthly_billing_demand_peaks_w_sys[0],
rate.rate_scale[i], i, last_excess_dollars);
rate.rate_scale[i], i, last_excess_dollars_w_sys);
}
}
else // monthly reconciliation per 2015.6.30 release
Expand All @@ -1174,11 +1184,11 @@ class cm_utilityrate5 : public compute_module
&monthly_excess_dollars_earned[0],
&monthly_nm_dollars_applied[0],
&monthly_excess_kwhs_earned[0],
&rate.dc_hourly_peak[0], &monthly_cumulative_excess_energy[0], &monthly_cumulative_excess_dollars[0],
&rate.dc_hourly_peak[0], &monthly_cumulative_excess_energy_w_sys[0], &monthly_cumulative_excess_dollars_w_sys[0],
&monthly_bill[0], &monthly_true_up_credits[0],
&monthly_billing_demand_peaks_w_sys[0],
rate.rate_scale[i], i,
&last_month, last_excess_energy, last_excess_dollars);
&last_month_w_sys, last_excess_energy_w_sys, last_excess_dollars_w_sys);
}
if (two_meter)
{
Expand Down Expand Up @@ -1392,7 +1402,7 @@ class cm_utilityrate5 : public compute_module
assign("year1_monthly_electricity_to_grid", var_data(&monthly_elec_to_grid[0], 12));
assign("year1_monthly_electricity_needed_from_grid", var_data(&monthly_elec_needed_from_grid[0], 12));

assign("year1_monthly_cumulative_excess_generation", var_data(&monthly_cumulative_excess_energy[0], 12));
assign("year1_monthly_cumulative_excess_generation", var_data(&monthly_cumulative_excess_energy_w_sys[0], 12));
assign("year1_monthly_utility_bill_w_sys", var_data(&monthly_bill[0], 12));

// output and demand per Paul's email 9/10/10
Expand Down
94 changes: 77 additions & 17 deletions test/ssc_test/cmod_utilityrate5_test.cpp
Expand Up @@ -395,13 +395,21 @@ TEST(cmod_utilityrate5_eqns, Test_Residential_net_metering_credits_in_may_with_r

ensure_outputs_line_up(data);

ssc_number_t cost_without_system;
ssc_data_get_number(data, "elec_cost_without_system_year1", &cost_without_system);
EXPECT_NEAR(771.8, cost_without_system, 0.1);
int nrows;
int ncols;
ssc_number_t* annual_bills_ub = ssc_data_get_array(data, "elec_cost_with_system", &nrows);
std::vector<double> annual_bill_w_sys(nrows);
annual_bill_w_sys = util::array_to_vector(annual_bills_ub, nrows);

ssc_number_t cost_with_system;
ssc_data_get_number(data, "elec_cost_with_system_year1", &cost_with_system);
EXPECT_NEAR(36.6, cost_with_system, 0.1);
EXPECT_NEAR(36.6, annual_bill_w_sys[1], 0.1);
EXPECT_NEAR(13.8, annual_bill_w_sys[2], 0.1);

ssc_number_t* annual_bills_ub_no_sys = ssc_data_get_array(data, "elec_cost_without_system", &nrows);
std::vector<double> annual_bill_wo_sys(nrows);
annual_bill_wo_sys = util::array_to_vector(annual_bills_ub_no_sys, nrows);

EXPECT_NEAR(771.8, annual_bill_wo_sys[1], 0.1);
EXPECT_NEAR(791.1, annual_bill_wo_sys[2], 0.1);

int length;
ssc_number_t* true_up_dollars = ssc_data_get_array(data, "year1_true_up_credits", &length);
Expand All @@ -413,8 +421,6 @@ TEST(cmod_utilityrate5_eqns, Test_Residential_net_metering_credits_in_may_with_r
float june_dollars = excess_dollars[credit_month + 1];
EXPECT_NEAR(11.37, june_dollars, 0.1);

int nrows;
int ncols;
ssc_number_t* annual_bills = ssc_data_get_matrix(data, "utility_bill_w_sys_ym", &nrows, &ncols);
util::matrix_t<double> bill_matrix(nrows, ncols);
bill_matrix.assign(annual_bills, nrows, ncols);
Expand Down Expand Up @@ -487,34 +493,88 @@ TEST(cmod_utilityrate5_eqns, Test_Residential_TOU_Rates_net_metering_credits) {
setup_residential_rates(data); // No sell rate in the defaults, so no credits
ssc_data_set_number(data, "ur_metering_option", 1);

int analysis_period = 1;
int analysis_period = 25;
ssc_data_set_number(data, "system_use_lifetime_output", 1);
ssc_data_set_number(data, "analysis_period", analysis_period);
set_array(data, "load", load_profile_path, 8760);
set_array(data, "gen", subhourly_gen_path, 8760 * 4); // 15 min data
set_array(data, "gen", commercial_gen_path, 8760 * 25);

int status = run_module(data, "utilityrate5");
EXPECT_FALSE(status);

ensure_outputs_line_up(data);
int nrows;
int ncols;
ssc_number_t* annual_bills_ub = ssc_data_get_array(data, "elec_cost_with_system", &nrows);
std::vector<double> annual_bill_w_sys(nrows);
annual_bill_w_sys = util::array_to_vector(annual_bills_ub, nrows);

ssc_number_t cost_without_system;
ssc_data_get_number(data, "elec_cost_without_system_year1", &cost_without_system);
EXPECT_NEAR(771.8, cost_without_system, 0.1); // Same as hourly, good!
EXPECT_NEAR(0, annual_bill_w_sys[1], 0.1);
EXPECT_NEAR(0, annual_bill_w_sys[2], 0.1);

ssc_number_t cost_with_system;
ssc_data_get_number(data, "elec_cost_with_system_year1", &cost_with_system);
EXPECT_NEAR(81.4, cost_with_system, 0.1);
ssc_number_t* annual_bills_ub_no_sys = ssc_data_get_array(data, "elec_cost_without_system", &nrows);
std::vector<double> annual_bill_wo_sys(nrows);
annual_bill_wo_sys = util::array_to_vector(annual_bills_ub_no_sys, nrows);

EXPECT_NEAR(771.8, annual_bill_wo_sys[1], 0.1);
EXPECT_NEAR(791.1, annual_bill_wo_sys[2], 0.1);

ssc_number_t* net_billing_credits = ssc_data_get_matrix(data, "nm_dollars_applied_ym", &nrows, &ncols);
util::matrix_t<double> credits_matrix(nrows, ncols);
credits_matrix.assign(net_billing_credits, nrows, ncols);

double dec_year_1_credits = credits_matrix.at((size_t)1, (size_t)11);
EXPECT_NEAR(0, dec_year_1_credits, 0.1);

ssc_data_free(data);
}

TEST(cmod_utilityrate5_eqns, Test_Residential_TOU_Rates_net_metering_credits_w_sell_rates_and_rollover) {
ssc_data_t data = new var_table;

setup_residential_rates(data);
ssc_number_t p_ur_ec_tou_mat[24] = { 1, 1, 9.9999999999999998e+37, 0, 0.10000000000000001, 0.10000000000000001,
2, 1, 9.9999999999999998e+37, 0, 0.050000000000000003, 0.050000000000000003,
3, 1, 9.9999999999999998e+37, 0, 0.20000000000000001, 0.20000000000000001,
4, 1, 9.9999999999999998e+37, 0, 0.25, 0.25 };
ssc_data_set_matrix(data, "ur_ec_tou_mat", p_ur_ec_tou_mat, 4, 6);
ssc_data_set_number(data, "ur_metering_option", 1);
ssc_data_set_number(data, "ur_nm_credit_rollover", 1);

int analysis_period = 25;
ssc_data_set_number(data, "system_use_lifetime_output", 1);
ssc_data_set_number(data, "analysis_period", analysis_period);
set_array(data, "load", load_profile_path, 8760);
set_array(data, "gen", commercial_gen_path, 8760 * 25);

int status = run_module(data, "utilityrate5");
EXPECT_FALSE(status);

ensure_outputs_line_up(data);

int nrows;
int ncols;
ssc_number_t* annual_bills_ub = ssc_data_get_array(data, "elec_cost_with_system", &nrows);
std::vector<double> annual_bill_w_sys(nrows);
annual_bill_w_sys = util::array_to_vector(annual_bills_ub, nrows);

EXPECT_NEAR(-19600.58, annual_bill_w_sys[1], 0.1);
EXPECT_NEAR(-37439.55, annual_bill_w_sys[2], 0.1);

ssc_number_t* annual_bills_ub_no_sys = ssc_data_get_array(data, "elec_cost_without_system", &nrows);
std::vector<double> annual_bill_wo_sys(nrows);
annual_bill_wo_sys = util::array_to_vector(annual_bills_ub_no_sys, nrows);

EXPECT_NEAR(771.8, annual_bill_wo_sys[1], 0.1);
EXPECT_NEAR(791.1, annual_bill_wo_sys[2], 0.1);

ssc_number_t* net_billing_credits = ssc_data_get_matrix(data, "nm_dollars_applied_ym", &nrows, &ncols);
util::matrix_t<double> credits_matrix(nrows, ncols);
credits_matrix.assign(net_billing_credits, nrows, ncols);

double dec_year_1_credits = credits_matrix.at((size_t)1, (size_t)11);
EXPECT_NEAR(0, dec_year_1_credits, 0.1);

ssc_data_free(data);
}

Expand Down