From 49524b48e8fcc3b8755b6750a0ab5bde46e39faf Mon Sep 17 00:00:00 2001 From: Brian Mirletz Date: Mon, 16 Oct 2023 10:36:50 -0600 Subject: [PATCH] Ssc 1123 price signals to retail rate naming (#1064) * Rename confusing forecast enum to retail rate * rename additional comments and vartab info --- shared/lib_battery_dispatch.h | 2 +- shared/lib_battery_dispatch_automatic_btm.cpp | 6 +++--- shared/lib_battery_dispatch_automatic_btm.h | 4 ++-- shared/lib_utility_rate.cpp | 2 +- ssc/cmod_battery.cpp | 10 +++++----- .../lib_battery_dispatch_automatic_btm_test.cpp | 16 ++++++++-------- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/shared/lib_battery_dispatch.h b/shared/lib_battery_dispatch.h index 5fef65a53..eecb8ecb3 100644 --- a/shared/lib_battery_dispatch.h +++ b/shared/lib_battery_dispatch.h @@ -57,7 +57,7 @@ class dispatch_t public: enum FOM_MODES { FOM_AUTOMATED_ECONOMIC, FOM_PV_SMOOTHING, FOM_CUSTOM_DISPATCH, FOM_MANUAL }; - enum BTM_MODES { PEAK_SHAVING, MAINTAIN_TARGET, CUSTOM_DISPATCH, MANUAL, FORECAST, SELF_CONSUMPTION }; + enum BTM_MODES { PEAK_SHAVING, MAINTAIN_TARGET, CUSTOM_DISPATCH, MANUAL, RETAIL_RATE, SELF_CONSUMPTION }; enum METERING { BEHIND, FRONT }; enum WEATHER_FORECAST_CHOICE { WF_LOOK_AHEAD, WF_LOOK_BEHIND, WF_CUSTOM }; enum LOAD_FORECAST_CHOICE { LOAD_LOOK_AHEAD, LOAD_LOOK_BEHIND, LOAD_CUSTOM }; diff --git a/shared/lib_battery_dispatch_automatic_btm.cpp b/shared/lib_battery_dispatch_automatic_btm.cpp index 4dc065e18..8c1b5d640 100644 --- a/shared/lib_battery_dispatch_automatic_btm.cpp +++ b/shared/lib_battery_dispatch_automatic_btm.cpp @@ -173,7 +173,7 @@ double dispatch_automatic_behind_the_meter_t::power_grid_target() { return _P_ta void dispatch_automatic_behind_the_meter_t::setup_rate_forecast() { - if (_mode == dispatch_t::FORECAST) + if (_mode == dispatch_t::RETAIL_RATE) { forecast_setup rate_setup(_steps_per_hour, _nyears); @@ -196,7 +196,7 @@ void dispatch_automatic_behind_the_meter_t::update_dispatch(size_t year, size_t // [kWh] - the maximum energy that can be cycled double E_max = 0; - if (_mode == dispatch_t::FORECAST) + if (_mode == dispatch_t::RETAIL_RATE) { // Hourly rolling forecast horizon if ((hour_of_year != _hour_last_updated) || m_outage_manager->recover_from_outage) @@ -883,7 +883,7 @@ void dispatch_automatic_behind_the_meter_t::costToCycle() m_cycleCost = 0.01 * capacityPercentDamagePerCycle * m_battReplacementCostPerKWH[curr_year] * _Battery->get_params().nominal_energy; } else { - // Should only apply to BattWatts. BattWatts doesn't have price signal dispatch, so this is fine. + // Should only apply to BattWatts. BattWatts doesn't have retal rate dispatch, so this is fine. m_cycleCost = 0.0; } } diff --git a/shared/lib_battery_dispatch_automatic_btm.h b/shared/lib_battery_dispatch_automatic_btm.h index f59e50946..2d963a18a 100644 --- a/shared/lib_battery_dispatch_automatic_btm.h +++ b/shared/lib_battery_dispatch_automatic_btm.h @@ -37,7 +37,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "lib_utility_rate.h" /* - * Data for price signal dispatch (FORECAST) to compare dispatch plans in the cost_based_target_power function + * Data for retail rate dispatch to compare dispatch plans in the cost_based_target_power function */ struct dispatch_plan { @@ -154,7 +154,7 @@ class dispatch_automatic_behind_the_meter_t : public dispatch_automatic_t void target_power(double E_max, size_t idx, FILE* p = NULL, bool debug = false); void apply_target_power(size_t day_index); - /*! Functions used by price signal dispatch */ + /*! Functions used by retail rate dispatch */ double compute_costs(size_t idx, size_t year, size_t hour_of_year, FILE* p = NULL, bool debug = false); // Initial computation of no-dispatch costs, assigned hourly to grid points void cost_based_target_power(size_t idx, size_t year, size_t hour_of_year, double no_dispatch_cost, double E_max, FILE* p = NULL, const bool debug = false); // Optimizing loop, runs twelve possible dispatch scenarios void plan_dispatch_for_cost(dispatch_plan& plan, size_t idx, double E_max, double startingEnergy); // Generates each dispatch plan (input argument) diff --git a/shared/lib_utility_rate.cpp b/shared/lib_utility_rate.cpp index d192e2281..0092bb058 100644 --- a/shared/lib_utility_rate.cpp +++ b/shared/lib_utility_rate.cpp @@ -354,7 +354,7 @@ void UtilityRateForecast::initializeMonth(int month, size_t year) } else { // Standard demand charges - // Ignore any peak charges lower than the average gross load - this prevents the price signal from showing demand charges on the first hour of each month when the load is not really a peak + // Ignore any peak charges lower than the average gross load - this prevents the retail rate forcast from showing demand charges on the first hour of each month when the load is not really a peak double avg_load = m_monthly_avg_load_forecast[year * 12 + month]; curr_month.dc_flat_peak = avg_load; for (int period = 0; period < (int)curr_month.dc_periods.size(); period++) diff --git a/ssc/cmod_battery.cpp b/ssc/cmod_battery.cpp index 0840d463f..e2e334d3e 100644 --- a/ssc/cmod_battery.cpp +++ b/ssc/cmod_battery.cpp @@ -162,7 +162,7 @@ var_info vtab_battery_inputs[] = { { SSC_INPUT, SSC_ARRAY, "batt_target_power_monthly", "Grid target power on monthly basis", "kW", "", "BatteryDispatch", "en_batt=1&batt_meter_position=0&batt_dispatch_choice=1", "", "" }, { SSC_INPUT, SSC_NUMBER, "batt_target_choice", "Target power input option", "0/1", "0=InputMonthlyTarget,1=InputFullTimeSeries", "BatteryDispatch", "en_batt=1&en_standalone_batt=0&batt_meter_position=0&batt_dispatch_choice=1", "", "" }, { SSC_INPUT, SSC_ARRAY, "batt_custom_dispatch", "Custom battery power for every time step", "kW", "kWAC if AC-connected, else kWDC", "BatteryDispatch", "en_batt=1&en_standalone_batt=0&batt_dispatch_choice=2","", "" }, - { SSC_INPUT, SSC_NUMBER, "batt_dispatch_choice", "Battery dispatch algorithm", "0/1/2/3/4/5", "If behind the meter: 0=PeakShaving,1=InputGridTarget,2=InputBatteryPower,3=ManualDispatch,4=PriceSignalForecast,5=SelfConsumption if front of meter: 0=AutomatedEconomic,1=PV_Smoothing,2=InputBatteryPower,3=ManualDispatch", "BatteryDispatch", "en_batt=1", "", "" }, + { SSC_INPUT, SSC_NUMBER, "batt_dispatch_choice", "Battery dispatch algorithm", "0/1/2/3/4/5", "If behind the meter: 0=PeakShaving,1=InputGridTarget,2=InputBatteryPower,3=ManualDispatch,4=RetailRateDispatch,5=SelfConsumption if front of meter: 0=AutomatedEconomic,1=PV_Smoothing,2=InputBatteryPower,3=ManualDispatch", "BatteryDispatch", "en_batt=1", "", "" }, { SSC_INPUT, SSC_NUMBER, "batt_dispatch_auto_can_fuelcellcharge", "Charging from fuel cell allowed for automated dispatch?", "0/1", "", "BatteryDispatch", "", "", "" }, { SSC_INPUT, SSC_NUMBER, "batt_dispatch_auto_can_gridcharge", "Grid charging allowed for automated dispatch?", "0/1", "", "BatteryDispatch", "", "", "" }, { SSC_INPUT, SSC_NUMBER, "batt_dispatch_auto_can_charge", "System charging allowed for automated dispatch?", "0/1", "", "BatteryDispatch", "", "", "" }, @@ -1036,7 +1036,7 @@ battstor::battstor(var_table& vt, bool setup_model, size_t nrec, double dt_hr, c } - bool cycleCostRelevant = (batt_vars->batt_meter_position == dispatch_t::BEHIND && batt_vars->batt_dispatch == dispatch_t::FORECAST) || + bool cycleCostRelevant = (batt_vars->batt_meter_position == dispatch_t::BEHIND && batt_vars->batt_dispatch == dispatch_t::RETAIL_RATE) || (batt_vars->batt_meter_position == dispatch_t::FRONT && (batt_vars->batt_dispatch != dispatch_t::FOM_MANUAL && batt_vars->batt_dispatch != dispatch_t::FOM_CUSTOM_DISPATCH)); if (cycleCostRelevant && batt_vars->batt_cycle_cost_choice == dispatch_t::MODEL_CYCLE_COST) { outCostToCycle = vt.allocate("batt_cost_to_cycle", nrec * nyears); @@ -1383,7 +1383,7 @@ void battstor::parse_configuration() prediction_index = 0; if (batt_meter_position == dispatch_t::BEHIND) { - if (batt_dispatch == dispatch_t::PEAK_SHAVING || batt_dispatch == dispatch_t::MAINTAIN_TARGET || batt_dispatch == dispatch_t::FORECAST || + if (batt_dispatch == dispatch_t::PEAK_SHAVING || batt_dispatch == dispatch_t::MAINTAIN_TARGET || batt_dispatch == dispatch_t::RETAIL_RATE || batt_dispatch == dispatch_t::SELF_CONSUMPTION) { switch (batt_weather_forecast) { @@ -1781,7 +1781,7 @@ bool battstor::uses_forecast() { return batt_vars->batt_dispatch == dispatch_t::FOM_AUTOMATED_ECONOMIC || batt_vars->batt_dispatch == dispatch_t::FOM_PV_SMOOTHING; } else { - return batt_vars->batt_dispatch == dispatch_t::FORECAST || dispatch_t::PEAK_SHAVING; + return batt_vars->batt_dispatch == dispatch_t::RETAIL_RATE || dispatch_t::PEAK_SHAVING; } } @@ -1946,7 +1946,7 @@ void battstor::outputs_topology_dependent() } } - bool cycleCostRelevant = (batt_vars->batt_meter_position == dispatch_t::BEHIND && batt_vars->batt_dispatch == dispatch_t::FORECAST) || + bool cycleCostRelevant = (batt_vars->batt_meter_position == dispatch_t::BEHIND && batt_vars->batt_dispatch == dispatch_t::RETAIL_RATE) || (batt_vars->batt_meter_position == dispatch_t::FRONT && (batt_vars->batt_dispatch != dispatch_t::FOM_MANUAL && batt_vars->batt_dispatch != dispatch_t::FOM_CUSTOM_DISPATCH)); if (cycleCostRelevant && batt_vars->batt_cycle_cost_choice == dispatch_t::MODEL_CYCLE_COST) { outCostToCycle[index] = (ssc_number_t)(dispatch_model->cost_to_cycle_per_kwh()); diff --git a/test/shared_test/lib_battery_dispatch_automatic_btm_test.cpp b/test/shared_test/lib_battery_dispatch_automatic_btm_test.cpp index 77d1a7781..1194fc7e4 100644 --- a/test/shared_test/lib_battery_dispatch_automatic_btm_test.cpp +++ b/test/shared_test/lib_battery_dispatch_automatic_btm_test.cpp @@ -308,7 +308,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, TestBasicForecast) { dispatchAutoBTM = new dispatch_automatic_behind_the_meter_t(batteryModel, dtHour, SOC_min, SOC_max, currentChoice, max_current, max_current, max_power, max_power, max_power, max_power, - 0, dispatch_t::BTM_MODES::FORECAST, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, 0, 1, 24, 1, true, + 0, dispatch_t::BTM_MODES::RETAIL_RATE, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, 0, 1, 24, 1, true, true, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); @@ -364,7 +364,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, TestSummerPeak) { dispatchAutoBTM = new dispatch_automatic_behind_the_meter_t(batteryModel, dtHour, SOC_min, SOC_max, currentChoice, max_current, max_current, max_power, max_power, max_power, max_power, - 0, dispatch_t::BTM_MODES::FORECAST, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, 0, 1, 24, 1, true, + 0, dispatch_t::BTM_MODES::RETAIL_RATE, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, 0, 1, 24, 1, true, true, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); @@ -404,7 +404,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, TestSummerPeakNetMeteringCredits) { dispatchAutoBTM = new dispatch_automatic_behind_the_meter_t(batteryModel, dtHour, SOC_min, SOC_max, currentChoice, max_current, max_current, max_power, max_power, max_power, max_power, - 0, dispatch_t::BTM_MODES::FORECAST, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, 0, 1, 24, 1, true, + 0, dispatch_t::BTM_MODES::RETAIL_RATE, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, 0, 1, 24, 1, true, true, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); @@ -444,7 +444,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, TestSummerPeakGridCharging) { dispatchAutoBTM = new dispatch_automatic_behind_the_meter_t(batteryModel, dtHour, SOC_min, SOC_max, currentChoice, max_current, max_current, max_power, max_power, max_power, max_power, - 0, dispatch_t::BTM_MODES::FORECAST, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, 0, 1, 24, 1, true, + 0, dispatch_t::BTM_MODES::RETAIL_RATE, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, 0, 1, 24, 1, true, true, canGridCharge, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); @@ -485,7 +485,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, TestSummerPeakGridChargingSubhourly) { dispatchAutoBTM = new dispatch_automatic_behind_the_meter_t(batteryModel, dtHour, SOC_min, SOC_max, currentChoice, max_current, max_current, max_power, max_power, max_power, max_power, - 0, dispatch_t::BTM_MODES::FORECAST, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, 0, 1, 24, 1, true, + 0, dispatch_t::BTM_MODES::RETAIL_RATE, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, 0, 1, 24, 1, true, true, canGridCharge, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); @@ -539,7 +539,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, TestCommercialPeakForecasting) { dispatchAutoBTM = new dispatch_automatic_behind_the_meter_t(batteryModel, dtHour, SOC_min, SOC_max, currentChoice, max_current, max_current, max_power, max_power, max_power, max_power, - 0, dispatch_t::BTM_MODES::FORECAST, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, 0, 1, 24, 1, true, + 0, dispatch_t::BTM_MODES::RETAIL_RATE, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, 0, 1, 24, 1, true, true, true, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); @@ -1224,7 +1224,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMGridOutagePeakShavingEmp } -TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMGridOutagePriceSignalsEmptyAndFull) { +TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMGridOutageRetailRAteEmptyAndFull) { double dtHour = 1; CreateBattery(dtHour); @@ -1236,7 +1236,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMGridOutagePriceSignalsEm dispatchAutoBTM = new dispatch_automatic_behind_the_meter_t(batteryModel, dtHour, SOC_min, SOC_max, currentChoice, max_current, max_current, max_power * defaultEff, max_power / defaultEff, max_power, max_power, - 0, dispatch_t::BTM_MODES::FORECAST, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, 0, 1, 24, 1, true, + 0, dispatch_t::BTM_MODES::RETAIL_RATE, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, 0, 1, 24, 1, true, true, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD);