@@ -129,11 +129,13 @@ rate_data::rate_data() :
129129 dc_hourly_peak(),
130130 monthly_dc_fixed(12 ),
131131 monthly_dc_tou(12 ),
132- en_ec_billing_demand(false ),
132+ uses_billing_demand(false ),
133+ en_billing_demand_lookback(false ),
133134 prev_peak_demand(12 ),
134- ec_bd_lookback_percents(12 ),
135- ec_bd_minimum(0.0 ),
136- ec_bd_lookback_months(1 ),
135+ bd_lookback_percents(12 ),
136+ bd_minimum(0.0 ),
137+ bd_lookback_months(1 ),
138+ bd_tou_periods(),
137139 billing_demand(12 ),
138140 tou_demand_single_peak(false ),
139141 enable_nm(false ),
@@ -160,11 +162,13 @@ rate_data::rate_data(const rate_data& tmp) :
160162 dc_hourly_peak(tmp.dc_hourly_peak),
161163 monthly_dc_fixed(tmp.monthly_dc_fixed),
162164 monthly_dc_tou(tmp.monthly_dc_tou),
163- en_ec_billing_demand(tmp.en_ec_billing_demand),
165+ uses_billing_demand(tmp.uses_billing_demand),
166+ en_billing_demand_lookback(tmp.en_billing_demand_lookback),
164167 prev_peak_demand(tmp.prev_peak_demand),
165- ec_bd_lookback_percents(tmp.ec_bd_lookback_percents),
166- ec_bd_minimum(tmp.ec_bd_minimum),
167- ec_bd_lookback_months(tmp.ec_bd_lookback_months),
168+ bd_lookback_percents(tmp.bd_lookback_percents),
169+ bd_minimum(tmp.bd_minimum),
170+ bd_lookback_months(tmp.bd_lookback_months),
171+ bd_tou_periods(tmp.bd_tou_periods),
168172 billing_demand(tmp.billing_demand),
169173 tou_demand_single_peak(tmp.tou_demand_single_peak),
170174 enable_nm(tmp.enable_nm),
@@ -215,37 +219,64 @@ bool rate_data::check_for_kwh_per_kw_rate(int units) {
215219
216220double rate_data::get_billing_demand (int month) {
217221 int m = 0 ;
218- double billing_demand = ec_bd_minimum ;
219- int prev_yr_lookback = 11 - (ec_bd_lookback_months - month); // What month do we stop looking back in the prev yr?
222+ double billing_demand = bd_minimum ;
223+ int prev_yr_lookback = 11 - (bd_lookback_months - month); // What month do we stop looking back in the prev yr?
220224
221225 for (m = 11 ; m >= prev_yr_lookback && m >= 0 ; m--) {
222- double ratchet_percent = ec_bd_lookback_percents [m] * 0.01 ;
226+ double ratchet_percent = bd_lookback_percents [m] * 0.01 ;
223227 double months_demand = prev_peak_demand[m] * ratchet_percent;
224228 if (months_demand > billing_demand) {
225229 billing_demand = months_demand;
226230 }
227231 }
228232
229233 int start_month = 0 ;
230- if (month >= ec_bd_lookback_months ) {
231- start_month = month - ec_bd_lookback_months ;
234+ if (month >= bd_lookback_months ) {
235+ start_month = month - bd_lookback_months ;
232236 }
233237
238+ int idx = 0 ;
234239 for (m = start_month; m <= month; m++) {
235- double ratchet_percent = ec_bd_lookback_percents[m] * 0.01 ;
236- double months_demand = m_month[m].dc_flat_peak * ratchet_percent;
237- if (months_demand > billing_demand) {
238- billing_demand = months_demand;
240+ idx = 0 ;
241+ for (int p : m_month[m].dc_periods ) {
242+ if (bd_tou_periods.at (p)) {
243+ double ratchet_percent = bd_lookback_percents[m] * 0.01 ;
244+ double months_demand = m_month[m].dc_tou_peak [idx] * ratchet_percent;
245+ if (months_demand > billing_demand) {
246+ billing_demand = months_demand;
247+ }
248+ }
249+ idx++;
239250 }
240251 }
241252
242- if (m_month[month].dc_flat_peak > billing_demand && m_month[month].use_current_month_ratchet ) {
243- billing_demand = m_month[month].dc_flat_peak ;
253+ if (m_month[month].use_current_month_ratchet ) {
254+ idx = 0 ;
255+ for (int p : m_month[month].dc_periods ) {
256+ if (bd_tou_periods.at (p)) {
257+ double months_demand = m_month[month].dc_tou_peak [idx];
258+ if (months_demand > billing_demand) {
259+ billing_demand = months_demand;
260+ }
261+ }
262+ idx++;
263+ }
244264 }
245265
246266 return billing_demand;
247267}
248268
269+ void rate_data::set_billing_demands () {
270+ for (int m = 0 ; m < (int ) m_month.size (); m++) {
271+ double flat_peak = m_month[m].dc_flat_peak ;
272+ if (en_billing_demand_lookback) {
273+ // If ratchets are present the peak used here might be the actual peak, or something based on a previous month.
274+ flat_peak = get_billing_demand (m);
275+ }
276+ billing_demand[m] = flat_peak;
277+ }
278+ }
279+
249280void rate_data::setup_prev_demand (ssc_number_t * prev_demand) {
250281 for (size_t i = 0 ; i < prev_peak_demand.size (); i++) {
251282 prev_peak_demand[i] = prev_demand[i];
@@ -277,13 +308,8 @@ void rate_data::init_energy_rates(bool gen_only) {
277308 std::vector<size_t > tier_numbers;
278309 std::vector<double > tier_kwh;
279310
280- // track monthly peak to determine which kWh/kW tier
281- double flat_peak = m_month[m].dc_flat_peak ;
282- if (en_ec_billing_demand) {
283- // If ratchets are present the peak used here might be the actual peak, or something based on a previous month.
284- flat_peak = get_billing_demand (m);
285- }
286- billing_demand[m] = flat_peak;
311+ // Monthly billing demand is computed prior to this loop
312+ double flat_peak = billing_demand[m];
287313
288314 // get kWh/kW break points based on actual demand
289315 for (size_t i_tier = 0 ; i_tier < m_month[m].ec_tou_units .ncols (); i_tier++)
@@ -805,7 +831,7 @@ void rate_data::setup_demand_charges(ssc_number_t* dc_weekday, ssc_number_t* dc_
805831 }
806832}
807833
808- void rate_data::setup_ratcheting_demand (ssc_number_t * ratchet_percent_matrix)
834+ void rate_data::setup_ratcheting_demand (ssc_number_t * ratchet_percent_matrix, ssc_number_t * bd_tou_period_matrix )
809835{
810836 // Error checked in SSC variables
811837 size_t nrows = 12 ;
@@ -814,10 +840,16 @@ void rate_data::setup_ratcheting_demand(ssc_number_t* ratchet_percent_matrix)
814840 ratchet_matrix.assign (ratchet_percent_matrix, nrows, ncols);
815841
816842 for (int i = 0 ; i < nrows; i++) {
817- ec_bd_lookback_percents [i] = ratchet_matrix.at (i, 0 );
843+ bd_lookback_percents [i] = ratchet_matrix.at (i, 0 );
818844 m_month[i].use_current_month_ratchet = ratchet_matrix.at (i, 1 ) == 1 ;
819845 }
820846
847+ nrows = m_dc_tou_periods.size ();
848+ util::matrix_t <double > tou_matrix (nrows, ncols);
849+ tou_matrix.assign (bd_tou_period_matrix, nrows, ncols);
850+ for (int i = 0 ; i < nrows; i++) {
851+ bd_tou_periods.emplace ((int ) tou_matrix.at (i, 0 ), tou_matrix.at (i, 1 ) == 1.0 );
852+ }
821853}
822854
823855void rate_data::sort_energy_to_periods (int month, double energy, size_t step) {
@@ -881,7 +913,7 @@ ssc_number_t rate_data::get_demand_charge(int month, size_t year)
881913 ssc_number_t charge = 0 ;
882914 ssc_number_t d_lower = 0 ;
883915 ssc_number_t total_charge = 0 ;
884- ssc_number_t demand = curr_month. dc_flat_peak ;
916+ ssc_number_t demand = billing_demand[month] ;
885917 bool found = false ;
886918 for (tier = 0 ; tier < (int )curr_month.dc_flat_ub .size () && !found; tier++)
887919 {
@@ -915,11 +947,19 @@ ssc_number_t rate_data::get_demand_charge(int month, size_t year)
915947 d_lower = 0 ;
916948 if (tou_demand_single_peak)
917949 {
918- demand = curr_month.dc_flat_peak ;
950+ // If billing demand lookback is not enabled, this will be the flat peak
951+ demand = billing_demand[month];
919952 if (curr_month.dc_flat_peak_hour != curr_month.dc_tou_peak_hour [period]) continue ; // only one peak per month.
920953 }
921- else if (period < curr_month.dc_periods .size ())
922- demand = curr_month.dc_tou_peak [period];
954+ else if (period < curr_month.dc_periods .size ()) {
955+ int period_num = curr_month.dc_periods [period];
956+ if (en_billing_demand_lookback && bd_tou_periods.at (period_num)) {
957+ demand = billing_demand[month];
958+ }
959+ else {
960+ demand = curr_month.dc_tou_peak [period];
961+ }
962+ }
923963 // find tier corresponding to peak demand
924964 found = false ;
925965 for (tier = 0 ; tier < (int )curr_month.dc_tou_ub .ncols () && !found; tier++)
0 commit comments