From dc483af06911a213d87dbb7b59136044af5a45ea Mon Sep 17 00:00:00 2001 From: Matt Prilliman <54449384+mjprilliman@users.noreply.github.com> Date: Thu, 3 Oct 2024 15:36:11 -0500 Subject: [PATCH 1/8] Initial cmod, hybrids updates for renaming generic system --- ssc/CMakeLists.txt | 2 +- ssc/cmod_custom_generation.cpp | 260 ++++++++++++++++++ ssc/cmod_hybrid.cpp | 4 +- ssc/common.cpp | 8 +- ssc/sscapi.cpp | 4 +- ..._battery_dispatch_pvsmoothing_fom_test.cpp | 2 +- test/ssc_test/cmod_generic_test.cpp | 12 +- test/ssc_test/cmod_hybrid_test.cpp | 2 +- 8 files changed, 277 insertions(+), 17 deletions(-) create mode 100644 ssc/cmod_custom_generation.cpp diff --git a/ssc/CMakeLists.txt b/ssc/CMakeLists.txt index 26e967246..cdec44432 100644 --- a/ssc/CMakeLists.txt +++ b/ssc/CMakeLists.txt @@ -32,6 +32,7 @@ set(SSC_SRC cmod_csp_subcomponent.cpp cmod_csp_trough_eqns.cpp cmod_csp_trough_eqns.h + cmod_custom_generation.cpp cmod_etes_electric_resistance.cpp cmod_etes_ptes.cpp cmod_equpartflip.cpp @@ -44,7 +45,6 @@ set(SSC_SRC cmod_fuelcell.h cmod_generic_system-builder.cpp cmod_generic_system-builder.h - cmod_generic_system.cpp cmod_geothermal.cpp cmod_geothermal_costs.cpp cmod_grid.cpp diff --git a/ssc/cmod_custom_generation.cpp b/ssc/cmod_custom_generation.cpp new file mode 100644 index 000000000..36296b272 --- /dev/null +++ b/ssc/cmod_custom_generation.cpp @@ -0,0 +1,260 @@ +/* +BSD 3-Clause License + +Copyright (c) Alliance for Sustainable Energy, LLC. See also https://github.com/NREL/ssc/blob/develop/LICENSE +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "core.h" +#include "lib_windfile.h" +#include "lib_windwatts.h" + +// for adjustment factors +#include "common.h" + +static var_info _cm_vtab_custom_generation[] = { +// VARTYPE DATATYPE NAME LABEL UNITS META GROUP REQUIRED_IF CONSTRAINTS UI_HINTS + { SSC_INPUT, SSC_NUMBER, "spec_mode", "Spec mode: 0=constant CF,1=profile", "", "", "Plant", "*", "", "" }, + { SSC_INPUT, SSC_NUMBER, "derate", "Derate", "%", "", "Plant", "*", "", "" }, + { SSC_INOUT, SSC_NUMBER, "system_capacity", "Nameplace Capcity", "kW", "", "Plant", "*", "", "" }, + { SSC_INPUT, SSC_NUMBER, "user_capacity_factor", "Capacity Factor", "%", "", "Plant", "*", "", "" }, + { SSC_INPUT, SSC_NUMBER, "heat_rate", "Heat Rate", "MMBTUs/MWhe", "", "Plant", "*", "", "" }, + { SSC_INPUT, SSC_NUMBER, "conv_eff", "Conversion Efficiency", "%", "", "Plant", "*", "", "" }, + { SSC_INPUT, SSC_ARRAY, "energy_output_array", "Array of Energy Output Profile", "kW", "", "Plant", "spec_mode=1", "", "" }, + + // optional for lifetime analysis + { SSC_INPUT, SSC_NUMBER, "system_use_lifetime_output", "Generic lifetime simulation", "0/1", "", "Lifetime", "?=0", "INTEGER,MIN=0,MAX=1", "" }, + { SSC_INPUT, SSC_NUMBER, "analysis_period", "Lifetime analysis period", "years", "", "Lifetime", "system_use_lifetime_output=1", "", "" }, + { SSC_INPUT, SSC_ARRAY, "generic_degradation", "Annual AC degradation", "%/year", "", "Lifetime", "system_use_lifetime_output=1", "", "" }, + + +// OUTPUTS ---------------------------------------------------------------------------- +// VARTYPE DATATYPE NAME LABEL UNITS META GROUP REQUIRED_IF CONSTRAINTS UI_HINTS +// { SSC_OUTPUT, SSC_ARRAY, "hourly_energy", "Hourly Energy", "kWh", "", "Time Series", "*", "LENGTH=8760", "" }, + { SSC_OUTPUT, SSC_ARRAY, "monthly_energy", "Monthly Energy Gross", "kWh", "", "Monthly", "*", "LENGTH=12", "" }, + { SSC_OUTPUT, SSC_NUMBER, "annual_energy", "Annual Energy", "kWh", "", "Annual", "*", "", "" }, + + { SSC_OUTPUT, SSC_NUMBER, "annual_fuel_usage", "Annual Fuel Usage", "kWht", "", "Annual", "*", "", "" }, + { SSC_OUTPUT, SSC_NUMBER, "water_usage", "Annual Water Usage", "", "", "Annual", "*", "", "" }, + { SSC_OUTPUT, SSC_NUMBER, "system_heat_rate", "Heat Rate Conversion Factor", "MMBTUs/MWhe", "", "Annual", "*", "", "" }, + + { SSC_OUTPUT, SSC_NUMBER, "capacity_factor", "Capacity factor", "%", "", "Annual", "*", "", "" }, + { SSC_OUTPUT, SSC_NUMBER, "kwh_per_kw", "First year kWh/kW", "kWh/kW", "", "Annual", "*", "", "" }, + + +var_info_invalid }; + +class cm_custom_generation : public compute_module +{ +private: +public: + + cm_custom_generation() + { + add_var_info( _cm_vtab_custom_generation ); + + // performance adjustment factors + add_var_info(vtab_adjustment_factors); + add_var_info(vtab_technology_outputs); + add_var_info(vtab_hybrid_tech_om_outputs); + } + + void exec( ) + { + int spec_mode = as_integer("spec_mode"); + bool system_use_lifetime_output = (as_integer("system_use_lifetime_output") == 1); + + // Warning workaround + static bool is32BitLifetime = (__ARCHBITS__ == 32 && system_use_lifetime_output); + if (is32BitLifetime) + throw exec_error( "generic", "Lifetime simulation of generic systems is only available in the 64 bit version of SAM."); + + // Lifetime setup + ssc_number_t *enet = nullptr; + size_t nyears = 1; + if (system_use_lifetime_output) { + nyears = as_integer("analysis_period"); + } + + // Load parsing + std::vector load; + size_t nrec_load = 8760; + + if (is_assigned("load")) { + load = as_vector_double("load"); + nrec_load = load.size(); + } + size_t nlifetime = nrec_load * nyears; + size_t steps_per_hour = nrec_load / 8760; + double ts_hour = 1 / (double)(steps_per_hour); + + // Degradation and adjustments + std::vector sys_degradation; + sys_degradation.reserve(nyears); + double derate = (1 - (double)as_number("derate") / 100); + + adjustment_factors haf(this, "adjust"); + if (!haf.setup(nrec_load, nyears)) + throw exec_error("generic system", "failed to setup adjustment factors: " + haf.error()); + + if (system_use_lifetime_output) + { + // setup system degradation + size_t i, count_degrad = 0; + ssc_number_t *degrad = 0; + degrad = as_array("generic_degradation", &count_degrad); + + if (count_degrad == 1) + { + for (i = 0; i < nyears; i++) + sys_degradation.push_back((ssc_number_t)pow((1.0 - (double)degrad[0] / 100.0), i)); + } + else if (count_degrad > 0) + { + for (i = 0; i < nyears && i < (int)count_degrad; i++) sys_degradation.push_back((ssc_number_t)(1.0 - (double)degrad[i] / 100.0)); + } + } + else { + sys_degradation.push_back(1); // single year mode - degradation handled in financial models. + } + + size_t idx = 0; + double annual_output = 0; + + // Constant generation profile + if (spec_mode == 0) + { + double output = (double)as_number("system_capacity") + * (double)as_number("user_capacity_factor") / 100 + * derate; // kW + + annual_output = 8760 * output; // kWh + enet = allocate("gen", nlifetime); + for (size_t iyear = 0; iyear < nyears; iyear++) + { + for (size_t ihour = 0; ihour < 8760; ihour++) + { + for (size_t ihourstep = 0; ihourstep < steps_per_hour; ihourstep++) + { + enet[idx] = (ssc_number_t)(output*haf(ihour)) * sys_degradation[iyear]; // kW + idx++; + } + } + } + } + // Input generation profile + else + { + size_t nrec_gen = 0; + ssc_number_t *enet_in = as_array("energy_output_array", &nrec_gen); // kW + size_t steps_per_hour_gen = nrec_gen / 8760; + + if (!enet_in) { + throw exec_error("generic", util::format("energy_output_array variable had no values.")); + } + + if (nrec_gen < nrec_load) { + throw exec_error("generic", util::format("energy_output_array %d must be greater than or equal to load array %d", nrec_gen, nrec_load)); + } + else { + nlifetime = nrec_gen * nyears; + steps_per_hour = steps_per_hour_gen; + ts_hour = 1 / (double)(steps_per_hour); + } + + enet = allocate("gen", nlifetime); + for (size_t iyear = 0; iyear < nyears; iyear++){ + for (size_t ihour = 0; ihour < 8760; ihour++){ + for (size_t ihourstep = 0; ihourstep < steps_per_hour_gen; ihourstep++) + { + enet[idx] = enet_in[ihour* steps_per_hour_gen + ihourstep] * (ssc_number_t)(derate* haf(ihour))* sys_degradation[iyear]; + idx++; + } + } + } + } + double annual_ac_pre_avail = 0, annual_energy = 0; + idx = 0; + + // Run generic system + for (size_t iyear = 0; iyear < nyears; iyear++){ + for (size_t hour = 0; hour < 8760; hour++){ + for (size_t jj = 0; jj < steps_per_hour; jj++) + { + + // accumulate system generation before curtailment and availability + if (iyear == 0) { + annual_ac_pre_avail += enet[idx] * ts_hour; + } + + //apply availability and curtailment + enet[idx] *= haf(hour); + + if (iyear == 0) { + annual_energy += (ssc_number_t)(enet[idx] * ts_hour); + } + + idx++; + } + } + } + + ssc_number_t* p_annual_energy_dist_time = gen_heatmap(this, steps_per_hour); + + accumulate_monthly_for_year("gen", "monthly_energy", ts_hour, steps_per_hour); + annual_output = accumulate_annual_for_year("gen", "annual_energy", ts_hour, steps_per_hour); + + // if conversion efficiency is zero then set fuel usage to zero per email from Paul 5/17/12 + double fuel_usage = 0.0; + if (as_double("conv_eff") != 0.0) + fuel_usage = annual_output * 100.0 / as_double("conv_eff"); + assign("annual_fuel_usage", (ssc_number_t)fuel_usage); + + assign("water_usage", 0.0); + assign("system_heat_rate", (ssc_number_t)(as_number("heat_rate") * as_number("conv_eff") / 100.0)); + + // metric outputs moved to technology + double kWhperkW = 0.0; + double nameplate = as_double("system_capacity"); + + + if (nameplate <= 0) { + nameplate = annual_output / (8760 * (double)(as_number("user_capacity_factor") / 100) * derate); + } + assign("system_capacity", (var_data)((ssc_number_t)nameplate)); + + if (nameplate > 0) { + kWhperkW = annual_output / nameplate; + } + assign("capacity_factor", var_data((ssc_number_t)(kWhperkW / 87.6))); + assign("kwh_per_kw", var_data((ssc_number_t)kWhperkW)); + } // exec +}; + +DEFINE_MODULE_ENTRY( custom_generation, "Custom Generation Profile", 1 ); + diff --git a/ssc/cmod_hybrid.cpp b/ssc/cmod_hybrid.cpp index 3054c84dc..104653ca9 100644 --- a/ssc/cmod_hybrid.cpp +++ b/ssc/cmod_hybrid.cpp @@ -91,7 +91,7 @@ class cm_hybrid : public compute_module for (size_t i = 0; i < vec_cms.size(); i++) { std::string computemodulename = vec_cms[i].str; - if ((computemodulename == "pvsamv1") || (computemodulename == "pvwattsv8") || (computemodulename == "windpower") || (computemodulename == "generic_system")) + if ((computemodulename == "pvsamv1") || (computemodulename == "pvwattsv8") || (computemodulename == "windpower") || (computemodulename == "custom_generation")) generators.push_back(computemodulename); else if (computemodulename == "battery") batteries.push_back(computemodulename); @@ -216,7 +216,7 @@ class cm_hybrid : public compute_module else { size_t count_degrad = 0; ssc_number_t* degrad = input.as_array("degradation", &count_degrad); - if (compute_module == "generic_system") + if (compute_module == "custom_generation") input.assign("generic_degradation", *input.lookup("degradation")); if (count_degrad == 1) { for (int i = 1; i <= analysisPeriod; i++) diff --git a/ssc/common.cpp b/ssc/common.cpp index baaf04f0d..6cfb99acd 100644 --- a/ssc/common.cpp +++ b/ssc/common.cpp @@ -109,10 +109,10 @@ var_info vtab_oandm[] = { { SSC_INPUT, SSC_NUMBER, "om_production_escal", "Production-based O&M escalation", "%/year", "", "System Costs", "?=0.0", "", "" }, { SSC_INPUT, SSC_ARRAY, "om_capacity", "Capacity-based O&M amount", "$/kWcap", "!battery,!fuelcell", "System Costs", "?=0.0", "", "" }, { SSC_INPUT, SSC_NUMBER, "om_capacity_escal", "Capacity-based O&M escalation", "%/year", "", "System Costs", "?=0.0", "", "" }, -{ SSC_INPUT, SSC_ARRAY, "om_fuel_cost", "Fuel cost", "$/MMBtu", "generic_system,fuelcell,tcslinearfresnel,tcstroughempirical,tcsgenericsolar,fresnelphysical", "System Costs", "?=0.0", "", "" }, -{ SSC_INPUT, SSC_NUMBER, "om_fuel_cost_escal", "Fuel cost escalation", "%/year", "generic_system,fuelcell,tcslinearfresnel,tcstroughempirical,tcsgenericsolar,fresnelphysical", "System Costs", "?=0.0", "", "" }, -{ SSC_INPUT, SSC_NUMBER, "annual_fuel_usage", "Fuel usage (yr 1)", "kWht", "generic_system,fuelcell,tcslinearfresnel,tcstroughempirical,tcsgenericsolar,fresnelphysical", "System Costs", "?=0", "MIN=0", "" }, -{ SSC_INPUT, SSC_ARRAY, "annual_fuel_usage_lifetime", "Fuel usage (lifetime)", "kWht", "generic_system,fuelcell,tcslinearfresnel,tcstroughempirical,tcsgenericsolar,fresnelphysical", "System Costs", "", "", "" }, +{ SSC_INPUT, SSC_ARRAY, "om_fuel_cost", "Fuel cost", "$/MMBtu", "custom_generation,fuelcell,tcslinearfresnel,tcstroughempirical,tcsgenericsolar,fresnelphysical", "System Costs", "?=0.0", "", "" }, +{ SSC_INPUT, SSC_NUMBER, "om_fuel_cost_escal", "Fuel cost escalation", "%/year", "custom_generation,fuelcell,tcslinearfresnel,tcstroughempirical,tcsgenericsolar,fresnelphysical", "System Costs", "?=0.0", "", "" }, +{ SSC_INPUT, SSC_NUMBER, "annual_fuel_usage", "Fuel usage (yr 1)", "kWht", "custom_generation,fuelcell,tcslinearfresnel,tcstroughempirical,tcsgenericsolar,fresnelphysical", "System Costs", "?=0", "MIN=0", "" }, +{ SSC_INPUT, SSC_ARRAY, "annual_fuel_usage_lifetime", "Fuel usage (lifetime)", "kWht", "custom_generation,fuelcell,tcslinearfresnel,tcstroughempirical,tcsgenericsolar,fresnelphysical", "System Costs", "", "", "" }, // replacements { SSC_INPUT,SSC_ARRAY , "om_batt_replacement_cost" , "Replacement cost 1" , "$/kWh" , "battery" , "System Costs" , "?=0.0" , "" , ""}, diff --git a/ssc/sscapi.cpp b/ssc/sscapi.cpp index 05904cb2e..e8ad9f96d 100644 --- a/ssc/sscapi.cpp +++ b/ssc/sscapi.cpp @@ -103,7 +103,7 @@ extern module_entry_info cm_entry_geothermal_costs, cm_entry_windpower, cm_entry_snowmodel, - cm_entry_generic_system, + cm_entry_custom_generation, cm_entry_wfcsvconv, cm_entry_tcstrough_empirical, cm_entry_tcstrough_physical, @@ -203,7 +203,7 @@ static module_entry_info *module_table[] = { &cm_entry_geothermal_costs, &cm_entry_windpower, &cm_entry_snowmodel, - &cm_entry_generic_system, + &cm_entry_custom_generation, &cm_entry_wfcsvconv, &cm_entry_tcstrough_empirical, &cm_entry_tcstrough_physical, diff --git a/test/shared_test/lib_battery_dispatch_pvsmoothing_fom_test.cpp b/test/shared_test/lib_battery_dispatch_pvsmoothing_fom_test.cpp index 5e7e44f16..e9af94db3 100644 --- a/test/shared_test/lib_battery_dispatch_pvsmoothing_fom_test.cpp +++ b/test/shared_test/lib_battery_dispatch_pvsmoothing_fom_test.cpp @@ -98,7 +98,7 @@ TEST_F(PVSmoothing_lib_battery_dispatch, Generic_w_PV_input_all_on) { // Run with fixed output // auto mod1 = ssc_module_create("generic_system"); - int errors = run_module(dat, "generic_system"); + int errors = run_module(dat, "custom_generation"); errors += run_module(dat, "battery"); // minimize memory usage for Travis // errors = run_module(dat, "grid"); diff --git a/test/ssc_test/cmod_generic_test.cpp b/test/ssc_test/cmod_generic_test.cpp index d9ab77a38..344479c0d 100644 --- a/test/ssc_test/cmod_generic_test.cpp +++ b/test/ssc_test/cmod_generic_test.cpp @@ -46,7 +46,7 @@ TEST_F(CMGeneric, SingleOwnerWithBattery_cmod_generic) { // Run with hourly data for (size_t i = 0; i < dispatch_options.size(); i++) { ssc_data_set_number(data, "batt_dispatch_choice", (ssc_number_t)dispatch_options[i]); - EXPECT_FALSE(run_module(data, "generic_system")); + EXPECT_FALSE(run_module(data, "custom_generation")); EXPECT_FALSE(run_module(data, "battery")); EXPECT_FALSE(run_module(data, "singleowner")); } @@ -57,7 +57,7 @@ TEST_F(CMGeneric, SingleOwnerWithBattery_cmod_generic) { set_array(data, "batt_room_temperature_celsius", generictest::temperature_path_30min, 8760 * 2); for (size_t i = 0; i < dispatch_options.size(); i++) { ssc_data_set_number(data, "batt_dispatch_choice", (ssc_number_t)dispatch_options[i]); - EXPECT_FALSE(run_module(data, "generic_system")); + EXPECT_FALSE(run_module(data, "custom_generation")); EXPECT_FALSE(run_module(data, "battery")); EXPECT_FALSE(run_module(data, "singleowner")); } @@ -65,7 +65,7 @@ TEST_F(CMGeneric, SingleOwnerWithBattery_cmod_generic) { // Test with incorrect combo of data sizes ssc_data_set_number(data, "batt_dispatch_choice", 3); set_array(data, "batt_custom_dispatch", generictest::batt_dispatch_path_30min, 8760*2); // 8760 or 8760 * 3 fails with execution error on Linux and windows - EXPECT_FALSE(run_module(data, "generic_system")); + EXPECT_FALSE(run_module(data, "custom_generation")); EXPECT_FALSE(run_module(data, "battery")); } @@ -82,7 +82,7 @@ TEST_F(CMGeneric, CommercialWithBattery_cmod_generic) { ssc_data_set_number(data, "system_use_lifetime_output", l); for (size_t i = 0; i < dispatch_options.size(); i++) { ssc_data_set_number(data, "batt_dispatch_choice", (ssc_number_t)dispatch_options[i]); - EXPECT_FALSE(run_module(data, "generic_system")); + EXPECT_FALSE(run_module(data, "custom_generation")); EXPECT_FALSE(run_module(data, "battery")); EXPECT_FALSE(run_module(data, "utilityrate5")); EXPECT_FALSE(run_module(data, "cashloan")); @@ -100,7 +100,7 @@ TEST_F(CMGeneric, CommercialWithBattery_cmod_generic) { ssc_data_set_number(data, "system_use_lifetime_output", l); for (size_t i = 0; i < dispatch_options.size(); i++) { ssc_data_set_number(data, "batt_dispatch_choice", (ssc_number_t)dispatch_options[i]); - EXPECT_FALSE(run_module(data, "generic_system")); + EXPECT_FALSE(run_module(data, "custom_generation")); EXPECT_FALSE(run_module(data, "battery")); EXPECT_FALSE(run_module(data, "utilityrate5")); EXPECT_FALSE(run_module(data, "cashloan")); @@ -116,7 +116,7 @@ TEST_F(CMGeneric, CommercialWithBattery_cmod_generic) { for (size_t l = 0; l < 2; l++) { ssc_data_set_number(data, "system_use_lifetime_output", l); - EXPECT_FALSE(run_module(data, "generic_system")); + EXPECT_FALSE(run_module(data, "custom_generation")); EXPECT_FALSE(run_module(data, "battery")); } } diff --git a/test/ssc_test/cmod_hybrid_test.cpp b/test/ssc_test/cmod_hybrid_test.cpp index 2be44c55d..17dd40043 100644 --- a/test/ssc_test/cmod_hybrid_test.cpp +++ b/test/ssc_test/cmod_hybrid_test.cpp @@ -183,7 +183,7 @@ TEST_F(CmodHybridTest, GenericPVWattsWindFuelCellBatteryHybrid_SingleOwner) { int len; auto outputs = ssc_data_get_table(dat, "output"); - auto gs_outputs = ssc_data_get_table(outputs, "generic_system"); + auto gs_outputs = ssc_data_get_table(outputs, "custom_generation"); ssc_data_get_number(gs_outputs, "annual_energy", &genericannualenergy); auto gs_om_expenses = ssc_data_get_array(gs_outputs, "cf_operating_expenses", &len); From d523fc1a8c64778e8ec9fcfdb965b19bf844baea Mon Sep 17 00:00:00 2001 From: Matt Prilliman <54449384+mjprilliman@users.noreply.github.com> Date: Fri, 4 Oct 2024 09:30:36 -0500 Subject: [PATCH 2/8] Rename generic system ssc tests --- .../custom_generation_common_data.h | 739 ++++++++++++++++++ .../batt_custom_dispatch.csv | 0 .../batt_custom_dispatch_30min.csv | 0 .../batt_custom_dispatch_60min.csv | 0 .../cp_variable_amount.csv | 0 .../cp_variable_percent_nameplate.csv | 0 .../curtailment_30min_0percent.csv | 0 .../curtailment_30min_50percent.csv | 0 .../dispatch_factors_ts.csv | 0 .../energy_output_array.csv | 0 .../energy_output_array_30min-2yr.csv | 0 .../energy_output_array_30min.csv | 0 .../energy_output_array_30min.xlsx | Bin .../energy_output_array_60min.csv | 0 .../generic.sam | Bin .../load.csv | 0 .../load_30min.csv | 0 .../load_60min.csv | 0 .../ur_ts_sell_rate.csv | 0 test/input_cases/generic_common_data.h | 44 +- test/input_cases/grid_common_data.h | 8 +- test/ssc_test/cmod_custom_generation_test.cpp | 139 ++++ test/ssc_test/cmod_custom_generation_test.h | 86 ++ test/ssc_test/cmod_generic_test.cpp | 44 +- test/ssc_test/cmod_generic_test.h | 8 +- 25 files changed, 1016 insertions(+), 52 deletions(-) create mode 100644 test/input_cases/custom_generation_common_data.h rename test/input_cases/{generic_system_data => custom_generation_data}/batt_custom_dispatch.csv (100%) rename test/input_cases/{generic_system_data => custom_generation_data}/batt_custom_dispatch_30min.csv (100%) rename test/input_cases/{generic_system_data => custom_generation_data}/batt_custom_dispatch_60min.csv (100%) rename test/input_cases/{generic_system_data => custom_generation_data}/cp_variable_amount.csv (100%) rename test/input_cases/{generic_system_data => custom_generation_data}/cp_variable_percent_nameplate.csv (100%) rename test/input_cases/{generic_system_data => custom_generation_data}/curtailment_30min_0percent.csv (100%) rename test/input_cases/{generic_system_data => custom_generation_data}/curtailment_30min_50percent.csv (100%) rename test/input_cases/{generic_system_data => custom_generation_data}/dispatch_factors_ts.csv (100%) rename test/input_cases/{generic_system_data => custom_generation_data}/energy_output_array.csv (100%) rename test/input_cases/{generic_system_data => custom_generation_data}/energy_output_array_30min-2yr.csv (100%) rename test/input_cases/{generic_system_data => custom_generation_data}/energy_output_array_30min.csv (100%) rename test/input_cases/{generic_system_data => custom_generation_data}/energy_output_array_30min.xlsx (100%) rename test/input_cases/{generic_system_data => custom_generation_data}/energy_output_array_60min.csv (100%) rename test/input_cases/{generic_system_data => custom_generation_data}/generic.sam (100%) rename test/input_cases/{generic_system_data => custom_generation_data}/load.csv (100%) rename test/input_cases/{generic_system_data => custom_generation_data}/load_30min.csv (100%) rename test/input_cases/{generic_system_data => custom_generation_data}/load_60min.csv (100%) rename test/input_cases/{generic_system_data => custom_generation_data}/ur_ts_sell_rate.csv (100%) create mode 100644 test/ssc_test/cmod_custom_generation_test.cpp create mode 100644 test/ssc_test/cmod_custom_generation_test.h diff --git a/test/input_cases/custom_generation_common_data.h b/test/input_cases/custom_generation_common_data.h new file mode 100644 index 000000000..0db351ac9 --- /dev/null +++ b/test/input_cases/custom_generation_common_data.h @@ -0,0 +1,739 @@ +/* +BSD 3-Clause License + +Copyright (c) Alliance for Sustainable Energy, LLC. See also https://github.com/NREL/ssc/blob/develop/LICENSE +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef _GENERIC_COMMON_DATA_H_ +#define _GENERIC_COMMON_DATA_H_ + +#include +#include "code_generator_utilities.h" + +namespace generictest { + char load_profile_path_60min[256]; + char load_profile_path_30min[256]; + char gen_path_60min[256]; + char gen_path_30min[256]; + char batt_dispatch_path_30min[256]; + char batt_dispatch_path_60min[256]; + char dispatch_factors_unused[256]; + char sell_rate_unused[256]; + char temperature_path[256]; + char temperature_path_30min[256]; + + + int n1 = sprintf(load_profile_path_60min, "%s/test/input_cases/generic_system_data/load_60min.csv",SSCDIR); + int n2 = sprintf(load_profile_path_30min, "%s/test/input_cases/generic_system_data/load_30min.csv",SSCDIR); + int n3 = sprintf(gen_path_60min, "%s/test/input_cases/generic_system_data/energy_output_array_60min.csv",SSCDIR); + int n4 = sprintf(gen_path_30min, "%s/test/input_cases/generic_system_data/energy_output_array_30min.csv",SSCDIR); + int n5 = sprintf(batt_dispatch_path_30min, "%s/test/input_cases/generic_system_data/batt_custom_dispatch_30min.csv",SSCDIR); + int n6 = sprintf(batt_dispatch_path_60min, "%s/test/input_cases/generic_system_data/batt_custom_dispatch_60min.csv",SSCDIR); + int n7 = sprintf(dispatch_factors_unused, "%s/test/input_cases/generic_system_data/dispatch_factors_ts.csv",SSCDIR); + int n8 = sprintf(sell_rate_unused, "%s/test/input_cases/generic_system_data/ur_ts_sell_rate.csv",SSCDIR); + int n9 = sprintf(temperature_path, "%s/test/input_cases/battery_data/batt_room_temperature_celsius_60min.csv",SSCDIR); + int n10 = sprintf(temperature_path_30min, "%s/test/input_cases/battery_data/batt_room_temperature_celsius_30min.csv",SSCDIR); +} + + +void generic_singleowner_battery_60min(ssc_data_t &data) +{ + ssc_data_set_number( data, "spec_mode", 1 ); + ssc_data_set_number( data, "derate", 0 ); + ssc_data_set_number( data, "system_capacity", 208842 ); + ssc_data_set_number( data, "user_capacity_factor", 43.599998474121094 ); + ssc_data_set_number( data, "heat_rate", 0 ); + ssc_data_set_number( data, "conv_eff", 0 ); + set_array( data, "energy_output_array", generictest::gen_path_60min, 8760); + ssc_data_set_number( data, "system_use_lifetime_output", 0 ); + ssc_data_set_number( data, "analysis_period", 25 ); + ssc_number_t p_generic_degradation[1] ={ 0 }; + ssc_data_set_array( data, "generic_degradation", p_generic_degradation, 1 ); + + ssc_data_set_number(data, "adjust_constant", 0.0); + + + ssc_data_set_number( data, "en_batt", 1 ); + ssc_data_set_number( data, "batt_replacement_option", 0 ); + ssc_data_set_number( data, "batt_chem", 1 ); + ssc_data_set_number( data, "batt_ac_or_dc", 1 ); + ssc_data_set_number( data, "batt_dc_dc_efficiency", 99 ); + ssc_data_set_number( data, "batt_dc_ac_efficiency", 96 ); + ssc_data_set_number( data, "batt_ac_dc_efficiency", 96 ); + ssc_data_set_number( data, "batt_meter_position", 1 ); + ssc_number_t p_batt_losses[1] ={ 0 }; + ssc_data_set_array( data, "batt_losses", p_batt_losses, 1 ); + ssc_number_t p_batt_losses_charging[12] ={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + ssc_data_set_array( data, "batt_losses_charging", p_batt_losses_charging, 12 ); + ssc_number_t p_batt_losses_discharging[12] ={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + ssc_data_set_array( data, "batt_losses_discharging", p_batt_losses_discharging, 12 ); + ssc_number_t p_batt_losses_idle[12] ={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + ssc_data_set_array( data, "batt_losses_idle", p_batt_losses_idle, 12 ); + ssc_data_set_number( data, "batt_loss_choice", 0 ); + ssc_data_set_number( data, "batt_current_choice", 1 ); + ssc_data_set_number( data, "batt_computed_strings", 1733583 ); + ssc_data_set_number( data, "batt_computed_series", 152 ); + ssc_data_set_number( data, "batt_computed_bank_capacity", 2000000 ); + ssc_data_set_number( data, "batt_current_charge_max", 1993620.375 ); + ssc_data_set_number( data, "batt_current_discharge_max", 1993620.375 ); + ssc_data_set_number( data, "batt_power_charge_max", 1000000 ); + ssc_data_set_number( data, "batt_power_discharge_max", 1000000 ); + ssc_data_set_number(data, "batt_inverter_efficiency_cutoff", 90); + ssc_data_set_number(data, "batt_power_charge_max_kwdc", 1000000); + ssc_data_set_number(data, "batt_power_discharge_max_kwdc", 1000000); + ssc_data_set_number(data, "batt_power_charge_max_kwac", 1000000); + ssc_data_set_number(data, "batt_power_discharge_max_kwac", 1000000); + ssc_data_set_number( data, "batt_voltage_choice", 0 ); + ssc_data_set_number( data, "batt_Vfull", 3.5999999046325684 ); + ssc_data_set_number( data, "batt_Vexp", 3.4000000953674316 ); + ssc_data_set_number( data, "batt_Vnom", 3.2999999523162842 ); + ssc_data_set_number(data, "batt_Vcut", 0.66 * 3.5999999046325684); + ssc_data_set_number( data, "batt_Vnom_default", 3.2999999523162842 ); + ssc_data_set_number( data, "batt_Qfull", 2.2999999523162842 ); + ssc_data_set_number( data, "batt_Qfull_flow", 3987240.75 ); + ssc_data_set_number( data, "batt_Qexp", 0.049910001456737518 ); + ssc_data_set_number( data, "batt_Qnom", 2.0446999073028564 ); + ssc_data_set_number( data, "batt_C_rate", 0.43000000715255737 ); + ssc_data_set_number( data, "batt_resistance", 0.0002 ); + ssc_number_t p_batt_voltage_matrix[2] ={ 0, 0 }; + ssc_data_set_matrix( data, "batt_voltage_matrix", p_batt_voltage_matrix, 1, 2 ); + ssc_data_set_number( data, "LeadAcid_q20_computed", 3987240.75 ); + ssc_data_set_number( data, "LeadAcid_q10_computed", 3708134 ); + ssc_data_set_number( data, "LeadAcid_qn_computed", 2392344.5 ); + ssc_data_set_number( data, "LeadAcid_tn", 1 ); + ssc_data_set_number( data, "batt_initial_SOC", 50 ); + ssc_data_set_number( data, "batt_minimum_SOC", 15 ); + ssc_data_set_number( data, "batt_maximum_SOC", 95 ); + ssc_data_set_number( data, "batt_minimum_modetime", 10 ); + ssc_data_set_number(data, "batt_life_model", 0); + ssc_number_t p_batt_lifetime_matrix[18] ={ 20, 0, 100, 20, 2500, 98, 20, 5000, 95, 80, 0, 100, 80, 500, 98, 80, 1000, 95 }; + ssc_data_set_matrix( data, "batt_lifetime_matrix", p_batt_lifetime_matrix, 6, 3 ); + ssc_data_set_number( data, "batt_calendar_choice", 1 ); + ssc_number_t p_batt_calendar_lifetime_matrix[6] ={ 0, 100, 3650, 80, 7300, 50 }; + ssc_data_set_matrix( data, "batt_calendar_lifetime_matrix", p_batt_calendar_lifetime_matrix, 3, 2 ); + ssc_data_set_number( data, "batt_calendar_q0", 1.0199999809265137 ); + ssc_data_set_number( data, "batt_calendar_a", 0.0026599999982863665 ); + ssc_data_set_number( data, "batt_calendar_b", -7280 ); + ssc_data_set_number( data, "batt_calendar_c", 930 ); + ssc_data_set_number( data, "batt_replacement_capacity", 0 ); + ssc_number_t p_batt_replacement_schedule[1] ={ 0 }; + ssc_data_set_array( data, "batt_replacement_schedule", p_batt_replacement_schedule, 1 ); + ssc_number_t p_replacement_cost[1] = { 600 }; + ssc_data_set_array(data, "om_batt_replacement_cost", p_replacement_cost, 1); + ssc_data_set_number( data, "batt_mass", 21489202 ); + ssc_data_set_number( data, "batt_surface_area", 2694 ); + ssc_data_set_number( data, "batt_Cp", 1004 ); + ssc_data_set_number( data, "batt_h_to_ambient", 20 ); + set_array(data, "batt_room_temperature_celsius", generictest::temperature_path, 8760); + ssc_number_t p_cap_vs_temp[8] ={ -10, 60, 0, 80, 25, 100, 40, 100 }; + ssc_data_set_matrix( data, "cap_vs_temp", p_cap_vs_temp, 4, 2 ); + ssc_number_t p_dispatch_manual_charge[6] ={ 1, 1, 1, 0, 0, 0 }; + ssc_data_set_array( data, "dispatch_manual_charge", p_dispatch_manual_charge, 6 ); + ssc_number_t p_dispatch_manual_discharge[6] ={ 0, 0, 1, 0, 0, 0 }; + ssc_data_set_array( data, "dispatch_manual_discharge", p_dispatch_manual_discharge, 6 ); + ssc_number_t p_dispatch_manual_gridcharge[6] ={ 0, 0, 0, 0, 0, 0 }; + ssc_data_set_array( data, "dispatch_manual_gridcharge", p_dispatch_manual_gridcharge, 6 ); + ssc_number_t p_dispatch_manual_percent_discharge[2] ={ 25, 0 }; + ssc_data_set_array( data, "dispatch_manual_percent_discharge", p_dispatch_manual_percent_discharge, 2 ); + ssc_number_t p_dispatch_manual_percent_gridcharge[1] ={ 0 }; + ssc_data_set_array( data, "dispatch_manual_percent_gridcharge", p_dispatch_manual_percent_gridcharge, 1 ); + ssc_number_t p_dispatch_manual_sched[288] ={ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1 }; + ssc_data_set_matrix( data, "dispatch_manual_sched", p_dispatch_manual_sched, 12, 24 ); + ssc_number_t p_dispatch_manual_sched_weekend[288] ={ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1 }; + ssc_data_set_matrix( data, "dispatch_manual_sched_weekend", p_dispatch_manual_sched_weekend, 12, 24 ); + set_array( data, "batt_custom_dispatch", generictest::batt_dispatch_path_60min, 8760); + ssc_data_set_number( data, "batt_dispatch_choice", 3 ); + ssc_number_t p_batt_pv_clipping_forecast[1] ={ 0 }; + ssc_data_set_array( data, "batt_pv_clipping_forecast", p_batt_pv_clipping_forecast, 1 ); + ssc_number_t p_batt_pv_dc_forecast[1] ={ 0 }; + ssc_data_set_array( data, "batt_pv_dc_forecast", p_batt_pv_dc_forecast, 1 ); + ssc_data_set_number( data, "batt_dispatch_auto_can_gridcharge", 0 ); + ssc_data_set_number( data, "batt_dispatch_auto_can_charge", 1 ); + ssc_data_set_number( data, "batt_dispatch_auto_can_clipcharge", 1 ); + ssc_data_set_number( data, "batt_auto_gridcharge_max_daily", 100 ); + ssc_data_set_number( data, "batt_look_ahead_hours", 18 ); + ssc_data_set_number( data, "batt_dispatch_update_frequency_hours", 1 ); + ssc_data_set_number( data, "batt_cycle_cost_choice", 0 ); + ssc_number_t p_batt_cycle_cost[1] = { 0.1 }; + ssc_data_set_array(data, "batt_cycle_cost", p_batt_cycle_cost, 1); + ssc_data_set_number( data, "en_electricity_rates", 0 ); + ssc_number_t p_ur_ec_sched_weekday[288] ={ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + ssc_data_set_matrix( data, "ur_ec_sched_weekday", p_ur_ec_sched_weekday, 12, 24 ); + ssc_number_t p_ur_ec_sched_weekend[288] ={ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + ssc_data_set_matrix( data, "ur_ec_sched_weekend", p_ur_ec_sched_weekend, 12, 24 ); + ssc_number_t p_ur_ec_tou_mat[30] ={ 1, 1, 9.9999996802856925e+37, 0, 0.094169996678829193, 0, 2, 1, 400, 0, 0.096869997680187225, 0, 2, 2, 800, 0, 0.13817000389099121, 0, 2, 3, 3000, 0, 0.16166999936103821, 0, 2, 4, 9.9999996802856925e+37, 0, 0.17257000505924225, 0 }; + ssc_data_set_matrix( data, "ur_ec_tou_mat", p_ur_ec_tou_mat, 5, 6 ); + ssc_data_set_number(data, "ur_en_ts_sell_rate", 0); + ssc_number_t p_ur_ts_buy_rate[1] = { 0 }; + ssc_data_set_array(data, "ur_ts_buy_rate", p_ur_ts_buy_rate, 1); + ssc_number_t p_ppa_price_input[1] = { 0 }; + ssc_data_set_array( data, "ppa_price_input", p_ppa_price_input, 1 ); + ssc_data_set_number(data, "cp_capacity_payment_esc", 0); + ssc_data_set_number(data, "cp_capacity_payment_type", 0); + ssc_data_set_number(data, "cp_system_nameplate", 0); + ssc_data_set_number(data, "cp_battery_nameplate", 0); + ssc_data_set_array(data, "cp_capacity_credit_percent", p_ppa_price_input, 1); + ssc_data_set_array( data, "cp_capacity_payment_amount", p_ppa_price_input, 1); + ssc_number_t p_dispatch_sched_weekday[288] ={ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + ssc_data_set_matrix( data, "dispatch_sched_weekday", p_dispatch_sched_weekday, 12, 24 ); + ssc_number_t p_dispatch_sched_weekend[288] ={ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + ssc_data_set_matrix( data, "dispatch_sched_weekend", p_dispatch_sched_weekend, 12, 24 ); + + ssc_number_t p_federal_tax_rate[1] ={ 21 }; + ssc_data_set_array( data, "federal_tax_rate", p_federal_tax_rate, 1 ); + ssc_number_t p_state_tax_rate[1] ={ 0 }; + ssc_data_set_array( data, "state_tax_rate", p_state_tax_rate, 1 ); + ssc_data_set_number( data, "property_tax_rate", 1 ); + ssc_data_set_number( data, "prop_tax_cost_assessed_percent", 100 ); + ssc_data_set_number( data, "prop_tax_assessed_decline", 0 ); + ssc_data_set_number( data, "real_discount_rate", 6.4000000953674316 ); + ssc_data_set_number( data, "inflation_rate", 2.5 ); + ssc_data_set_number( data, "insurance_rate", 1 ); + ssc_number_t p_om_fixed[1] ={ 0 }; + ssc_data_set_array( data, "om_fixed", p_om_fixed, 1 ); + ssc_data_set_number( data, "om_fixed_escal", 0 ); + ssc_number_t p_om_production[1] ={ 0 }; + ssc_data_set_array( data, "om_production", p_om_production, 1 ); + ssc_data_set_number( data, "om_production_escal", 0 ); + ssc_number_t p_om_capacity[1] ={ 50 }; + ssc_data_set_array( data, "om_capacity", p_om_capacity, 1 ); + ssc_data_set_number( data, "om_capacity_escal", 0 ); + ssc_number_t p_om_fuel_cost[1] ={ 0 }; + ssc_data_set_array( data, "om_fuel_cost", p_om_fuel_cost, 1 ); + ssc_data_set_number( data, "om_fuel_cost_escal", 0 ); + ssc_number_t itc_amount[1] = { 0 }; + ssc_number_t itc_fed_percent[1] = { 30 }; + ssc_number_t itc_sta_percent[1] = { 0 }; + ssc_number_t itc_amount_max[1] = { 1 }; + ssc_data_set_array(data, "itc_fed_amount", itc_amount, 1); + ssc_data_set_array(data, "itc_sta_amount", itc_amount, 1); + ssc_data_set_array(data, "itc_fed_percent", itc_fed_percent, 1); + ssc_data_set_array(data, "itc_sta_percent", itc_sta_percent, 1); + ssc_data_set_array(data, "itc_fed_percent_maxvalue", itc_amount_max, 1); + ssc_data_set_array(data, "itc_sta_percent_maxvalue", itc_amount_max, 1); + ssc_data_set_number( data, "itc_fed_amount_deprbas_fed", 1 ); + ssc_data_set_number( data, "itc_fed_amount_deprbas_sta", 1 ); + ssc_data_set_number( data, "itc_sta_amount_deprbas_fed", 0 ); + ssc_data_set_number( data, "itc_sta_amount_deprbas_sta", 0 ); + ssc_data_set_number( data, "itc_fed_percent_deprbas_fed", 1 ); + ssc_data_set_number( data, "itc_fed_percent_deprbas_sta", 1 ); + ssc_data_set_number( data, "itc_sta_percent_deprbas_fed", 0 ); + ssc_data_set_number( data, "itc_sta_percent_deprbas_sta", 0 ); + ssc_number_t p_ptc_fed_amount[1] ={ 0 }; + ssc_data_set_array( data, "ptc_fed_amount", p_ptc_fed_amount, 1 ); + ssc_data_set_number( data, "ptc_fed_term", 10 ); + ssc_data_set_number( data, "ptc_fed_escal", 0 ); + ssc_number_t p_ptc_sta_amount[1] ={ 0 }; + ssc_data_set_array( data, "ptc_sta_amount", p_ptc_sta_amount, 1 ); + ssc_data_set_number( data, "ptc_sta_term", 10 ); + ssc_data_set_number( data, "ptc_sta_escal", 0 ); + ssc_data_set_number( data, "ibi_fed_amount", 0 ); + ssc_data_set_number( data, "ibi_fed_amount_tax_fed", 1 ); + ssc_data_set_number( data, "ibi_fed_amount_tax_sta", 1 ); + ssc_data_set_number( data, "ibi_fed_amount_deprbas_fed", 0 ); + ssc_data_set_number( data, "ibi_fed_amount_deprbas_sta", 0 ); + ssc_data_set_number( data, "ibi_sta_amount", 0 ); + ssc_data_set_number( data, "ibi_sta_amount_tax_fed", 1 ); + ssc_data_set_number( data, "ibi_sta_amount_tax_sta", 1 ); + ssc_data_set_number( data, "ibi_sta_amount_deprbas_fed", 0 ); + ssc_data_set_number( data, "ibi_sta_amount_deprbas_sta", 0 ); + ssc_data_set_number( data, "ibi_uti_amount", 0 ); + ssc_data_set_number( data, "ibi_uti_amount_tax_fed", 1 ); + ssc_data_set_number( data, "ibi_uti_amount_tax_sta", 1 ); + ssc_data_set_number( data, "ibi_uti_amount_deprbas_fed", 0 ); + ssc_data_set_number( data, "ibi_uti_amount_deprbas_sta", 0 ); + ssc_data_set_number( data, "ibi_oth_amount", 0 ); + ssc_data_set_number( data, "ibi_oth_amount_tax_fed", 1 ); + ssc_data_set_number( data, "ibi_oth_amount_tax_sta", 1 ); + ssc_data_set_number( data, "ibi_oth_amount_deprbas_fed", 0 ); + ssc_data_set_number( data, "ibi_oth_amount_deprbas_sta", 0 ); + ssc_data_set_number( data, "ibi_fed_percent", 0 ); + ssc_data_set_number( data, "ibi_fed_percent_maxvalue", 0 ); + ssc_data_set_number( data, "ibi_fed_percent_tax_fed", 1 ); + ssc_data_set_number( data, "ibi_fed_percent_tax_sta", 1 ); + ssc_data_set_number( data, "ibi_fed_percent_deprbas_fed", 0 ); + ssc_data_set_number( data, "ibi_fed_percent_deprbas_sta", 0 ); + ssc_data_set_number( data, "ibi_sta_percent", 0 ); + ssc_data_set_number( data, "ibi_sta_percent_maxvalue", 0 ); + ssc_data_set_number( data, "ibi_sta_percent_tax_fed", 1 ); + ssc_data_set_number( data, "ibi_sta_percent_tax_sta", 1 ); + ssc_data_set_number( data, "ibi_sta_percent_deprbas_fed", 0 ); + ssc_data_set_number( data, "ibi_sta_percent_deprbas_sta", 0 ); + ssc_data_set_number( data, "ibi_uti_percent", 0 ); + ssc_data_set_number( data, "ibi_uti_percent_maxvalue", 0 ); + ssc_data_set_number( data, "ibi_uti_percent_tax_fed", 1 ); + ssc_data_set_number( data, "ibi_uti_percent_tax_sta", 1 ); + ssc_data_set_number( data, "ibi_uti_percent_deprbas_fed", 0 ); + ssc_data_set_number( data, "ibi_uti_percent_deprbas_sta", 0 ); + ssc_data_set_number( data, "ibi_oth_percent", 0 ); + ssc_data_set_number( data, "ibi_oth_percent_maxvalue", 0 ); + ssc_data_set_number( data, "ibi_oth_percent_tax_fed", 1 ); + ssc_data_set_number( data, "ibi_oth_percent_tax_sta", 1 ); + ssc_data_set_number( data, "ibi_oth_percent_deprbas_fed", 0 ); + ssc_data_set_number( data, "ibi_oth_percent_deprbas_sta", 0 ); + ssc_data_set_number( data, "cbi_fed_amount", 0 ); + ssc_data_set_number( data, "cbi_fed_maxvalue", 0 ); + ssc_data_set_number( data, "cbi_fed_tax_fed", 1 ); + ssc_data_set_number( data, "cbi_fed_tax_sta", 1 ); + ssc_data_set_number( data, "cbi_fed_deprbas_fed", 0 ); + ssc_data_set_number( data, "cbi_fed_deprbas_sta", 0 ); + ssc_data_set_number( data, "cbi_sta_amount", 0 ); + ssc_data_set_number( data, "cbi_sta_maxvalue", 0 ); + ssc_data_set_number( data, "cbi_sta_tax_fed", 1 ); + ssc_data_set_number( data, "cbi_sta_tax_sta", 1 ); + ssc_data_set_number( data, "cbi_sta_deprbas_fed", 0 ); + ssc_data_set_number( data, "cbi_sta_deprbas_sta", 0 ); + ssc_data_set_number( data, "cbi_uti_amount", 0 ); + ssc_data_set_number( data, "cbi_uti_maxvalue", 0 ); + ssc_data_set_number( data, "cbi_uti_tax_fed", 1 ); + ssc_data_set_number( data, "cbi_uti_tax_sta", 1 ); + ssc_data_set_number( data, "cbi_uti_deprbas_fed", 0 ); + ssc_data_set_number( data, "cbi_uti_deprbas_sta", 0 ); + ssc_data_set_number( data, "cbi_oth_amount", 0 ); + ssc_data_set_number( data, "cbi_oth_maxvalue", 0 ); + ssc_data_set_number( data, "cbi_oth_tax_fed", 1 ); + ssc_data_set_number( data, "cbi_oth_tax_sta", 1 ); + ssc_data_set_number( data, "cbi_oth_deprbas_fed", 0 ); + ssc_data_set_number( data, "cbi_oth_deprbas_sta", 0 ); + ssc_number_t p_pbi_fed_amount[1] ={ 0 }; + ssc_data_set_array( data, "pbi_fed_amount", p_pbi_fed_amount, 1 ); + ssc_data_set_number( data, "pbi_fed_term", 0 ); + ssc_data_set_number( data, "pbi_fed_escal", 0 ); + ssc_data_set_number( data, "pbi_fed_tax_fed", 1 ); + ssc_data_set_number( data, "pbi_fed_tax_sta", 1 ); + ssc_number_t p_pbi_sta_amount[1] ={ 0 }; + ssc_data_set_array( data, "pbi_sta_amount", p_pbi_sta_amount, 1 ); + ssc_data_set_number( data, "pbi_sta_term", 0 ); + ssc_data_set_number( data, "pbi_sta_escal", 0 ); + ssc_data_set_number( data, "pbi_sta_tax_fed", 1 ); + ssc_data_set_number( data, "pbi_sta_tax_sta", 1 ); + ssc_number_t p_pbi_uti_amount[1] ={ 0 }; + ssc_data_set_array( data, "pbi_uti_amount", p_pbi_uti_amount, 1 ); + ssc_data_set_number( data, "pbi_uti_term", 0 ); + ssc_data_set_number( data, "pbi_uti_escal", 0 ); + ssc_data_set_number( data, "pbi_uti_tax_fed", 1 ); + ssc_data_set_number( data, "pbi_uti_tax_sta", 1 ); + ssc_number_t p_pbi_oth_amount[1] ={ 0 }; + ssc_data_set_array( data, "pbi_oth_amount", p_pbi_oth_amount, 1 ); + ssc_data_set_number( data, "pbi_oth_term", 0 ); + ssc_data_set_number( data, "pbi_oth_escal", 0 ); + ssc_data_set_number( data, "pbi_oth_tax_fed", 1 ); + ssc_data_set_number( data, "pbi_oth_tax_sta", 1 ); + ssc_number_t p_degradation[1] ={ 0 }; + ssc_data_set_array( data, "degradation", p_degradation, 1 ); + ssc_data_set_number( data, "loan_moratorium", 0 ); + ssc_data_set_number( data, "system_use_recapitalization", 0 ); + ssc_data_set_number( data, "ppa_multiplier_model", 0 ); + set_array( data, "dispatch_factors_ts", generictest::dispatch_factors_unused, 8147); + ssc_number_t p_dispatch_tod_factors[9] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + ssc_data_set_array(data, "dispatch_tod_factors", p_dispatch_tod_factors, 9); + ssc_data_set_number( data, "total_installed_cost", 1554456064 ); + ssc_data_set_number( data, "reserves_interest", 1.75 ); + ssc_data_set_number( data, "equip1_reserve_cost", 0 ); + ssc_data_set_number( data, "equip1_reserve_freq", 0 ); + ssc_data_set_number( data, "equip2_reserve_cost", 0 ); + ssc_data_set_number( data, "equip2_reserve_freq", 0 ); + ssc_data_set_number( data, "equip3_reserve_cost", 0 ); + ssc_data_set_number( data, "equip3_reserve_freq", 0 ); + ssc_data_set_number( data, "equip_reserve_depr_sta", 0 ); + ssc_data_set_number( data, "equip_reserve_depr_fed", 0 ); + ssc_data_set_number( data, "salvage_percentage", 0 ); + ssc_data_set_number( data, "ppa_soln_mode", 1 ); + ssc_data_set_number( data, "ppa_escalation", 1 ); + ssc_data_set_number( data, "construction_financing_cost", 0 ); + ssc_data_set_number( data, "term_tenor", 0 ); + ssc_data_set_number( data, "term_int_rate", 0 ); + ssc_data_set_number( data, "dscr", 0 ); + ssc_data_set_number( data, "dscr_reserve_months", 0 ); + ssc_data_set_number( data, "debt_percent", 50 ); + ssc_data_set_number( data, "debt_option", 1 ); + ssc_data_set_number( data, "payment_option", 0 ); + ssc_data_set_number( data, "cost_debt_closing", 0 ); + ssc_data_set_number( data, "cost_debt_fee", 0 ); + ssc_data_set_number( data, "months_working_reserve", 6 ); + ssc_data_set_number( data, "months_receivables_reserve", 0 ); + ssc_data_set_number( data, "cost_other_financing", 0 ); + ssc_data_set_number( data, "flip_target_percent", 10 ); + ssc_data_set_number( data, "flip_target_year", 10 ); + ssc_data_set_number( data, "depr_alloc_macrs_5_percent", 100 ); + ssc_data_set_number( data, "depr_alloc_macrs_15_percent", 0 ); + ssc_data_set_number( data, "depr_alloc_sl_5_percent", 0 ); + ssc_data_set_number( data, "depr_alloc_sl_15_percent", 0 ); + ssc_data_set_number( data, "depr_alloc_sl_20_percent", 0 ); + ssc_data_set_number( data, "depr_alloc_sl_39_percent", 0 ); + ssc_data_set_number( data, "depr_alloc_custom_percent", 0 ); + ssc_number_t p_depr_custom_schedule[1] ={ 0 }; + ssc_data_set_array( data, "depr_custom_schedule", p_depr_custom_schedule, 1 ); + ssc_data_set_number( data, "depr_bonus_sta", 0 ); + ssc_data_set_number( data, "depr_bonus_sta_macrs_5", 0 ); + ssc_data_set_number( data, "depr_bonus_sta_macrs_15", 0 ); + ssc_data_set_number( data, "depr_bonus_sta_sl_5", 0 ); + ssc_data_set_number( data, "depr_bonus_sta_sl_15", 0 ); + ssc_data_set_number( data, "depr_bonus_sta_sl_20", 0 ); + ssc_data_set_number( data, "depr_bonus_sta_sl_39", 0 ); + ssc_data_set_number( data, "depr_bonus_sta_custom", 0 ); + ssc_data_set_number( data, "depr_bonus_fed", 0 ); + ssc_data_set_number( data, "depr_bonus_fed_macrs_5", 1 ); + ssc_data_set_number( data, "depr_bonus_fed_macrs_15", 0 ); + ssc_data_set_number( data, "depr_bonus_fed_sl_5", 0 ); + ssc_data_set_number( data, "depr_bonus_fed_sl_15", 0 ); + ssc_data_set_number( data, "depr_bonus_fed_sl_20", 0 ); + ssc_data_set_number( data, "depr_bonus_fed_sl_39", 0 ); + ssc_data_set_number( data, "depr_bonus_fed_custom", 0 ); + ssc_data_set_number( data, "depr_itc_sta_macrs_5", 0 ); + ssc_data_set_number( data, "depr_itc_sta_macrs_15", 0 ); + ssc_data_set_number( data, "depr_itc_sta_sl_5", 0 ); + ssc_data_set_number( data, "depr_itc_sta_sl_15", 0 ); + ssc_data_set_number( data, "depr_itc_sta_sl_20", 0 ); + ssc_data_set_number( data, "depr_itc_sta_sl_39", 0 ); + ssc_data_set_number( data, "depr_itc_sta_custom", 0 ); + ssc_data_set_number( data, "depr_itc_fed_macrs_5", 0 ); + ssc_data_set_number( data, "depr_itc_fed_macrs_15", 0 ); + ssc_data_set_number( data, "depr_itc_fed_sl_5", 0 ); + ssc_data_set_number( data, "depr_itc_fed_sl_15", 0 ); + ssc_data_set_number( data, "depr_itc_fed_sl_20", 0 ); + ssc_data_set_number( data, "depr_itc_fed_sl_39", 0 ); + ssc_data_set_number( data, "depr_itc_fed_custom", 0 ); + ssc_data_set_number( data, "pbi_fed_for_ds", 0 ); + ssc_data_set_number( data, "pbi_sta_for_ds", 0 ); + ssc_data_set_number( data, "pbi_uti_for_ds", 0 ); + ssc_data_set_number( data, "pbi_oth_for_ds", 0 ); + ssc_data_set_number( data, "depr_stabas_method", 1 ); + ssc_data_set_number( data, "depr_fedbas_method", 1 ); + ssc_data_set_number( data, "battery_per_kWh", 300 ); + ssc_data_set_number( data, "batt_replacement_cost_escal", 0 ); +} + +void generic_commerical_battery_60min(ssc_data_t &data) +{ + ssc_data_set_number(data, "spec_mode", 1); + ssc_data_set_number(data, "derate", 4); + ssc_data_set_number(data, "system_capacity", 1.7090300321578979); + ssc_data_set_number(data, "user_capacity_factor", 43.599998474121094); + ssc_data_set_number(data, "heat_rate", 10); + ssc_data_set_number(data, "conv_eff", 34.118049621582031); + set_array(data, "energy_output_array", generictest::gen_path_60min, 8760); + ssc_data_set_number(data, "system_use_lifetime_output", 0); + ssc_data_set_number(data, "analysis_period", 25); + ssc_number_t p_generic_degradation[1] = { 0 }; + ssc_data_set_array(data, "generic_degradation", p_generic_degradation, 1); + + ssc_data_set_number(data, "adjust_constant", 0.0); + + ssc_data_set_number(data, "en_batt", 1); + set_array(data, "load", generictest::load_profile_path_60min, 8760); + ssc_data_set_number(data, "batt_replacement_option", 0); + ssc_data_set_number(data, "batt_chem", 1); + ssc_data_set_number(data, "batt_ac_or_dc", 1); + ssc_data_set_number(data, "batt_dc_dc_efficiency", 98); + ssc_data_set_number(data, "batt_dc_ac_efficiency", 96); + ssc_data_set_number(data, "batt_ac_dc_efficiency", 96); + ssc_data_set_number(data, "batt_meter_position", 0); + ssc_number_t p_batt_losses[1] = { 0 }; + ssc_data_set_array(data, "batt_losses", p_batt_losses, 1); + ssc_number_t p_batt_losses_charging[1] = { 0 }; + ssc_data_set_array(data, "batt_losses_charging", p_batt_losses_charging, 1); + ssc_number_t p_batt_losses_discharging[1] = { 0 }; + ssc_data_set_array(data, "batt_losses_discharging", p_batt_losses_discharging, 1); + ssc_number_t p_batt_losses_idle[1] = { 0 }; + ssc_data_set_array(data, "batt_losses_idle", p_batt_losses_idle, 1); + ssc_data_set_number(data, "batt_loss_choice", 0); + ssc_data_set_number(data, "batt_current_choice", 1); + ssc_data_set_number(data, "batt_computed_strings", 89); + ssc_data_set_number(data, "batt_computed_series", 139); + ssc_data_set_number(data, "batt_computed_bank_capacity", 100.20510101318359); + ssc_data_set_number(data, "batt_current_charge_max", 100.125); + ssc_data_set_number(data, "batt_current_discharge_max", 100.125); + ssc_data_set_number(data, "batt_inverter_efficiency_cutoff", 90); + ssc_data_set_number(data, "batt_power_charge_max_kwdc", 50.10255050659179); + ssc_data_set_number(data, "batt_power_discharge_max_kwdc", 50.10255050659179); + ssc_data_set_number(data, "batt_power_charge_max_kwac", 50.10255050659179); + ssc_data_set_number(data, "batt_power_discharge_max_kwac", 50.10255050659179); + ssc_data_set_number(data, "batt_voltage_choice", 0); + ssc_data_set_number(data, "batt_Vfull", 4.0999999046325684); + ssc_data_set_number(data, "batt_Vexp", 4.0500001907348633); + ssc_data_set_number(data, "batt_Vnom", 3.4000000953674316); + ssc_data_set_number(data, "batt_Vcut", 0.66 * 4.0999999046325684); + ssc_data_set_number(data, "batt_Vnom_default", 3.5999999046325684); + ssc_data_set_number(data, "batt_Qfull", 2.25); + ssc_data_set_number(data, "batt_Qfull_flow", 200.25); + ssc_data_set_number(data, "batt_Qexp", 0.040049999952316284); + ssc_data_set_number(data, "batt_Qnom", 2.0002501010894775); + ssc_data_set_number(data, "batt_C_rate", 0.20000000298023224); + ssc_data_set_number(data, "batt_resistance", 0.0002); + ssc_number_t p_batt_voltage_matrix[12] = { 0, 1.2000000476837158, 20, 1.1000000238418579, 40, 1.0499999523162842, 60, 1, 80, 0.94999998807907104, 100, 0.5 }; + ssc_data_set_matrix(data, "batt_voltage_matrix", p_batt_voltage_matrix, 6, 2); + ssc_data_set_number(data, "LeadAcid_q20_computed", 200.25); + ssc_data_set_number(data, "LeadAcid_q10_computed", 186.23249816894531); + ssc_data_set_number(data, "LeadAcid_qn_computed", 120.15000152587891); + ssc_data_set_number(data, "LeadAcid_tn", 1); + ssc_data_set_number(data, "batt_initial_SOC", 50); + ssc_data_set_number(data, "batt_minimum_SOC", 15); + ssc_data_set_number(data, "batt_maximum_SOC", 95); + ssc_data_set_number(data, "batt_minimum_modetime", 10); + ssc_data_set_number(data, "batt_life_model", 0); + ssc_number_t p_batt_lifetime_matrix[18] = { 20, 0, 100, 20, 5000, 80, 20, 10000, 60, 80, 0, 100, 80, 1000, 80, 80, 2000, 60 }; + ssc_data_set_matrix(data, "batt_lifetime_matrix", p_batt_lifetime_matrix, 6, 3); + ssc_data_set_number(data, "batt_calendar_choice", 0); + ssc_number_t p_batt_calendar_lifetime_matrix[6] = { 0, 100, 3650, 80, 7300, 50 }; + ssc_data_set_matrix(data, "batt_calendar_lifetime_matrix", p_batt_calendar_lifetime_matrix, 3, 2); + ssc_data_set_number(data, "batt_calendar_q0", 1.0199999809265137); + ssc_data_set_number(data, "batt_calendar_a", 0.0026599999982863665); + ssc_data_set_number(data, "batt_calendar_b", -7280); + ssc_data_set_number(data, "batt_calendar_c", 930); + ssc_data_set_number(data, "batt_replacement_capacity", 0); + ssc_number_t p_batt_replacement_schedule[1] = { 0 }; + ssc_data_set_array(data, "batt_replacement_schedule", p_batt_replacement_schedule, 1); + ssc_number_t p_replacement_cost[1] = { 600 }; + ssc_data_set_array(data, "om_batt_replacement_cost", p_replacement_cost, 1); + ssc_data_set_number(data, "batt_cycle_cost_choice", 0); + ssc_number_t p_batt_cycle_cost[1] = { 0.1 }; + ssc_data_set_array(data, "batt_cycle_cost", p_batt_cycle_cost, 1); + ssc_data_set_number(data, "batt_mass", 507.8046875); + ssc_data_set_number(data, "batt_surface_area", 2.05); + ssc_data_set_number(data, "batt_Cp", 1000); + ssc_data_set_number(data, "batt_h_to_ambient", 20); + set_array(data, "batt_room_temperature_celsius", generictest::temperature_path, 8760); + ssc_number_t p_cap_vs_temp[8] = { -15, 65, 0, 85, 25, 100, 40, 104 }; + ssc_data_set_matrix(data, "cap_vs_temp", p_cap_vs_temp, 4, 2); + ssc_number_t p_dispatch_manual_charge[6] = { 1, 1, 1, 0, 0, 0 }; + ssc_data_set_array(data, "dispatch_manual_charge", p_dispatch_manual_charge, 6); + ssc_number_t p_dispatch_manual_discharge[6] = { 0, 0, 1, 0, 0, 0 }; + ssc_data_set_array(data, "dispatch_manual_discharge", p_dispatch_manual_discharge, 6); + ssc_number_t p_dispatch_manual_gridcharge[6] = { 0, 1, 0, 0, 0, 0 }; + ssc_data_set_array(data, "dispatch_manual_gridcharge", p_dispatch_manual_gridcharge, 6); + ssc_number_t p_dispatch_manual_discharge_to_grid[6] = { 0, 0, 0, 0, 0, 0 }; + ssc_data_set_array(data, "dispatch_manual_btm_discharge_to_grid", p_dispatch_manual_discharge_to_grid, 6); + ssc_number_t p_dispatch_manual_percent_discharge[2] = { 25, 0 }; + ssc_data_set_array(data, "dispatch_manual_percent_discharge", p_dispatch_manual_percent_discharge, 2); + ssc_number_t p_dispatch_manual_percent_gridcharge[2] = { 100, 0 }; + ssc_data_set_array(data, "dispatch_manual_percent_gridcharge", p_dispatch_manual_percent_gridcharge, 2); + ssc_number_t p_dispatch_manual_sched[288] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1 }; + ssc_data_set_matrix(data, "dispatch_manual_sched", p_dispatch_manual_sched, 12, 24); + ssc_number_t p_dispatch_manual_sched_weekend[288] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1 }; + ssc_data_set_matrix(data, "dispatch_manual_sched_weekend", p_dispatch_manual_sched_weekend, 12, 24); + ssc_number_t p_batt_target_power[1] = { 15 }; + ssc_data_set_array(data, "batt_target_power", p_batt_target_power, 1); + ssc_number_t p_batt_target_power_monthly[1] = { 0 }; + ssc_data_set_array(data, "batt_target_power_monthly", p_batt_target_power_monthly, 1); + ssc_data_set_number(data, "batt_target_choice", 0); + set_array(data, "batt_custom_dispatch", generictest::batt_dispatch_path_60min, 8760); + ssc_data_set_number(data, "batt_dispatch_choice", 3); + ssc_data_set_number(data, "batt_dispatch_auto_can_gridcharge", 0); + ssc_data_set_number(data, "batt_dispatch_auto_can_charge", 1); + ssc_data_set_number(data, "batt_dispatch_charge_only_system_exceeds_load", 1); + ssc_data_set_number(data, "batt_dispatch_discharge_only_load_exceeds_system", 1); + ssc_number_t p_ur_ec_sched_weekday[288] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + ssc_data_set_matrix(data, "ur_ec_sched_weekday", p_ur_ec_sched_weekday, 12, 24); + ssc_number_t p_ur_ec_sched_weekend[288] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + ssc_data_set_matrix(data, "ur_ec_sched_weekend", p_ur_ec_sched_weekend, 12, 24); + ssc_number_t p_ur_ec_tou_mat[30] = { 1, 1, 9.9999996802856925e+37, 0, 0.094169996678829193, 0, 2, 1, 400, 0, 0.096869997680187225, 0, 2, 2, 800, 0, 0.13817000389099121, 0, 2, 3, 3000, 0, 0.16166999936103821, 0, 2, 4, 9.9999996802856925e+37, 0, 0.17257000505924225, 0 }; + ssc_data_set_matrix(data, "ur_ec_tou_mat", p_ur_ec_tou_mat, 5, 6); + + ssc_data_set_number(data, "inflation_rate", 2.5); + ssc_number_t p_degradation[1] = { 0 }; + ssc_data_set_array(data, "degradation", p_degradation, 1); + ssc_number_t p_load_escalation[1] = { 0 }; + ssc_data_set_array(data, "load_escalation", p_load_escalation, 1); + ssc_number_t p_rate_escalation[1] = { 0 }; + ssc_data_set_array(data, "rate_escalation", p_rate_escalation, 1); + ssc_data_set_number(data, "ur_metering_option", 2); + ssc_data_set_number(data, "ur_nm_yearend_sell_rate", 0.027890000492334366); + ssc_data_set_number(data, "ur_monthly_fixed_charge", 8.5500001907348633); + ssc_data_set_number(data, "ur_monthly_min_charge", 0); + ssc_data_set_number(data, "ur_annual_min_charge", 0); + ssc_data_set_number(data, "ur_en_ts_sell_rate", 0); + set_array(data, "ur_ts_sell_rate", generictest::sell_rate_unused, 8760); + ssc_data_set_number(data, "ur_dc_enable", 1); + ssc_number_t p_ur_dc_sched_weekday[288] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + ssc_data_set_matrix(data, "ur_dc_sched_weekday", p_ur_dc_sched_weekday, 12, 24); + ssc_number_t p_ur_dc_sched_weekend[288] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + ssc_data_set_matrix(data, "ur_dc_sched_weekend", p_ur_dc_sched_weekend, 12, 24); + ssc_number_t p_ur_dc_tou_mat[4] = { 1, 1, 0, 0 }; + ssc_data_set_matrix(data, "ur_dc_tou_mat", p_ur_dc_tou_mat, 1, 4); + ssc_number_t p_ur_dc_flat_mat[48] = { 0, 1, 0, 0, 1, 1, 0, 0, 2, 1, 0, 0, 3, 1, 0, 0, 4, 1, 0, 0, 5, 1, 0, 0, 6, 1, 0, 0, 7, 1, 0, 0, 8, 1, 0, 0, 9, 1, 0, 0, 10, 1, 0, 0, 11, 1, 0, 0 }; + ssc_data_set_matrix(data, "ur_dc_flat_mat", p_ur_dc_flat_mat, 12, 4); + + ssc_number_t p_federal_tax_rate[1] = { 21 }; + ssc_data_set_array(data, "federal_tax_rate", p_federal_tax_rate, 1); + ssc_number_t p_state_tax_rate[1] = { 7 }; + ssc_data_set_array(data, "state_tax_rate", p_state_tax_rate, 1); + ssc_data_set_number(data, "property_tax_rate", 0); + ssc_data_set_number(data, "prop_tax_cost_assessed_percent", 100); + ssc_data_set_number(data, "prop_tax_assessed_decline", 0); + ssc_data_set_number(data, "real_discount_rate", 6.4000000953674316); + ssc_data_set_number(data, "insurance_rate", 0.5); + ssc_data_set_number(data, "loan_term", 25); + ssc_data_set_number(data, "loan_rate", 7.5); + ssc_data_set_number(data, "debt_fraction", 100); + ssc_number_t p_om_fixed[1] = { 0 }; + ssc_data_set_array(data, "om_fixed", p_om_fixed, 1); + ssc_data_set_number(data, "om_fixed_escal", 0); + ssc_number_t p_om_production[1] = { 0 }; + ssc_data_set_array(data, "om_production", p_om_production, 1); + ssc_data_set_number(data, "om_production_escal", 0); + ssc_number_t p_om_capacity[1] = { 25 }; + ssc_data_set_array(data, "om_capacity", p_om_capacity, 1); + ssc_data_set_number(data, "om_capacity_escal", 0); + ssc_number_t p_om_fuel_cost[1] = { 8 }; + ssc_data_set_array(data, "om_fuel_cost", p_om_fuel_cost, 1); + ssc_data_set_number(data, "om_fuel_cost_escal", 0); + ssc_data_set_number(data, "depr_fed_type", 1); + ssc_data_set_number(data, "depr_fed_sl_years", 7); + ssc_number_t p_depr_fed_custom[1] = { 0 }; + ssc_data_set_array(data, "depr_fed_custom", p_depr_fed_custom, 1); + ssc_data_set_number(data, "depr_sta_type", 1); + ssc_data_set_number(data, "depr_sta_sl_years", 7); + ssc_number_t p_depr_sta_custom[1] = { 0 }; + ssc_data_set_array(data, "depr_sta_custom", p_depr_sta_custom, 1); + ssc_number_t itc_amount[1] = { 0 }; + ssc_number_t itc_fed_percent[1] = { 0 }; + ssc_number_t itc_sta_percent[1] = { 0 }; + ssc_number_t itc_amount_max[1] = { 1e+38 }; + ssc_data_set_array(data, "itc_fed_amount", itc_amount, 1); + ssc_data_set_array(data, "itc_sta_amount", itc_amount, 1); + ssc_data_set_array(data, "itc_fed_percent", itc_fed_percent, 1); + ssc_data_set_array(data, "itc_sta_percent", itc_sta_percent, 1); + ssc_data_set_array(data, "itc_fed_percent_maxvalue", itc_amount_max, 1); + ssc_data_set_array(data, "itc_sta_percent_maxvalue", itc_amount_max, 1); + ssc_data_set_number(data, "itc_fed_amount_deprbas_fed", 1); + ssc_data_set_number(data, "itc_fed_amount_deprbas_sta", 1); + ssc_data_set_number(data, "itc_sta_amount_deprbas_fed", 0); + ssc_data_set_number(data, "itc_sta_amount_deprbas_sta", 0); + ssc_data_set_number(data, "itc_fed_percent_deprbas_fed", 1); + ssc_data_set_number(data, "itc_fed_percent_deprbas_sta", 1); + ssc_data_set_number(data, "itc_sta_percent_deprbas_fed", 0); + ssc_data_set_number(data, "itc_sta_percent_deprbas_sta", 0); + ssc_number_t p_ptc_fed_amount[1] = { 0 }; + ssc_data_set_array(data, "ptc_fed_amount", p_ptc_fed_amount, 1); + ssc_data_set_number(data, "ptc_fed_term", 10); + ssc_data_set_number(data, "ptc_fed_escal", 0); + ssc_number_t p_ptc_sta_amount[1] = { 0 }; + ssc_data_set_array(data, "ptc_sta_amount", p_ptc_sta_amount, 1); + ssc_data_set_number(data, "ptc_sta_term", 10); + ssc_data_set_number(data, "ptc_sta_escal", 0); + ssc_data_set_number(data, "ibi_fed_amount", 0); + ssc_data_set_number(data, "ibi_fed_amount_tax_fed", 1); + ssc_data_set_number(data, "ibi_fed_amount_tax_sta", 1); + ssc_data_set_number(data, "ibi_fed_amount_deprbas_fed", 0); + ssc_data_set_number(data, "ibi_fed_amount_deprbas_sta", 0); + ssc_data_set_number(data, "ibi_sta_amount", 0); + ssc_data_set_number(data, "ibi_sta_amount_tax_fed", 1); + ssc_data_set_number(data, "ibi_sta_amount_tax_sta", 1); + ssc_data_set_number(data, "ibi_sta_amount_deprbas_fed", 0); + ssc_data_set_number(data, "ibi_sta_amount_deprbas_sta", 0); + ssc_data_set_number(data, "ibi_uti_amount", 0); + ssc_data_set_number(data, "ibi_uti_amount_tax_fed", 1); + ssc_data_set_number(data, "ibi_uti_amount_tax_sta", 1); + ssc_data_set_number(data, "ibi_uti_amount_deprbas_fed", 0); + ssc_data_set_number(data, "ibi_uti_amount_deprbas_sta", 0); + ssc_data_set_number(data, "ibi_oth_amount", 0); + ssc_data_set_number(data, "ibi_oth_amount_tax_fed", 1); + ssc_data_set_number(data, "ibi_oth_amount_tax_sta", 1); + ssc_data_set_number(data, "ibi_oth_amount_deprbas_fed", 0); + ssc_data_set_number(data, "ibi_oth_amount_deprbas_sta", 0); + ssc_data_set_number(data, "ibi_fed_percent", 0); + ssc_data_set_number(data, "ibi_fed_percent_maxvalue", 9.9999996802856925e+37); + ssc_data_set_number(data, "ibi_fed_percent_tax_fed", 1); + ssc_data_set_number(data, "ibi_fed_percent_tax_sta", 1); + ssc_data_set_number(data, "ibi_fed_percent_deprbas_fed", 0); + ssc_data_set_number(data, "ibi_fed_percent_deprbas_sta", 0); + ssc_data_set_number(data, "ibi_sta_percent", 0); + ssc_data_set_number(data, "ibi_sta_percent_maxvalue", 9.9999996802856925e+37); + ssc_data_set_number(data, "ibi_sta_percent_tax_fed", 1); + ssc_data_set_number(data, "ibi_sta_percent_tax_sta", 1); + ssc_data_set_number(data, "ibi_sta_percent_deprbas_fed", 0); + ssc_data_set_number(data, "ibi_sta_percent_deprbas_sta", 0); + ssc_data_set_number(data, "ibi_uti_percent", 0); + ssc_data_set_number(data, "ibi_uti_percent_maxvalue", 9.9999996802856925e+37); + ssc_data_set_number(data, "ibi_uti_percent_tax_fed", 1); + ssc_data_set_number(data, "ibi_uti_percent_tax_sta", 1); + ssc_data_set_number(data, "ibi_uti_percent_deprbas_fed", 0); + ssc_data_set_number(data, "ibi_uti_percent_deprbas_sta", 0); + ssc_data_set_number(data, "ibi_oth_percent", 0); + ssc_data_set_number(data, "ibi_oth_percent_maxvalue", 9.9999996802856925e+37); + ssc_data_set_number(data, "ibi_oth_percent_tax_fed", 1); + ssc_data_set_number(data, "ibi_oth_percent_tax_sta", 1); + ssc_data_set_number(data, "ibi_oth_percent_deprbas_fed", 0); + ssc_data_set_number(data, "ibi_oth_percent_deprbas_sta", 0); + ssc_data_set_number(data, "cbi_fed_amount", 0); + ssc_data_set_number(data, "cbi_fed_maxvalue", 9.9999996802856925e+37); + ssc_data_set_number(data, "cbi_fed_tax_fed", 1); + ssc_data_set_number(data, "cbi_fed_tax_sta", 1); + ssc_data_set_number(data, "cbi_fed_deprbas_fed", 0); + ssc_data_set_number(data, "cbi_fed_deprbas_sta", 0); + ssc_data_set_number(data, "cbi_sta_amount", 0); + ssc_data_set_number(data, "cbi_sta_maxvalue", 9.9999996802856925e+37); + ssc_data_set_number(data, "cbi_sta_tax_fed", 1); + ssc_data_set_number(data, "cbi_sta_tax_sta", 1); + ssc_data_set_number(data, "cbi_sta_deprbas_fed", 0); + ssc_data_set_number(data, "cbi_sta_deprbas_sta", 0); + ssc_data_set_number(data, "cbi_uti_amount", 0); + ssc_data_set_number(data, "cbi_uti_maxvalue", 9.9999996802856925e+37); + ssc_data_set_number(data, "cbi_uti_tax_fed", 1); + ssc_data_set_number(data, "cbi_uti_tax_sta", 1); + ssc_data_set_number(data, "cbi_uti_deprbas_fed", 0); + ssc_data_set_number(data, "cbi_uti_deprbas_sta", 0); + ssc_data_set_number(data, "cbi_oth_amount", 0); + ssc_data_set_number(data, "cbi_oth_maxvalue", 9.9999996802856925e+37); + ssc_data_set_number(data, "cbi_oth_tax_fed", 1); + ssc_data_set_number(data, "cbi_oth_tax_sta", 1); + ssc_data_set_number(data, "cbi_oth_deprbas_fed", 0); + ssc_data_set_number(data, "cbi_oth_deprbas_sta", 0); + ssc_number_t p_pbi_fed_amount[1] = { 0 }; + ssc_data_set_array(data, "pbi_fed_amount", p_pbi_fed_amount, 1); + ssc_data_set_number(data, "pbi_fed_term", 0); + ssc_data_set_number(data, "pbi_fed_escal", 0); + ssc_data_set_number(data, "pbi_fed_tax_fed", 1); + ssc_data_set_number(data, "pbi_fed_tax_sta", 1); + ssc_number_t p_pbi_sta_amount[1] = { 0 }; + ssc_data_set_array(data, "pbi_sta_amount", p_pbi_sta_amount, 1); + ssc_data_set_number(data, "pbi_sta_term", 0); + ssc_data_set_number(data, "pbi_sta_escal", 0); + ssc_data_set_number(data, "pbi_sta_tax_fed", 1); + ssc_data_set_number(data, "pbi_sta_tax_sta", 1); + ssc_number_t p_pbi_uti_amount[1] = { 0 }; + ssc_data_set_array(data, "pbi_uti_amount", p_pbi_uti_amount, 1); + ssc_data_set_number(data, "pbi_uti_term", 0); + ssc_data_set_number(data, "pbi_uti_escal", 0); + ssc_data_set_number(data, "pbi_uti_tax_fed", 1); + ssc_data_set_number(data, "pbi_uti_tax_sta", 1); + ssc_number_t p_pbi_oth_amount[1] = { 0 }; + ssc_data_set_array(data, "pbi_oth_amount", p_pbi_oth_amount, 1); + ssc_data_set_number(data, "pbi_oth_term", 0); + ssc_data_set_number(data, "pbi_oth_escal", 0); + ssc_data_set_number(data, "pbi_oth_tax_fed", 1); + ssc_data_set_number(data, "pbi_oth_tax_sta", 1); + ssc_data_set_number(data, "battery_per_kWh", 300); + ssc_data_set_number(data, "batt_replacement_cost_escal", 0); + ssc_data_set_number(data, "total_installed_cost", 86827.921875); + ssc_data_set_number(data, "salvage_percentage", 0); +} +#endif diff --git a/test/input_cases/generic_system_data/batt_custom_dispatch.csv b/test/input_cases/custom_generation_data/batt_custom_dispatch.csv similarity index 100% rename from test/input_cases/generic_system_data/batt_custom_dispatch.csv rename to test/input_cases/custom_generation_data/batt_custom_dispatch.csv diff --git a/test/input_cases/generic_system_data/batt_custom_dispatch_30min.csv b/test/input_cases/custom_generation_data/batt_custom_dispatch_30min.csv similarity index 100% rename from test/input_cases/generic_system_data/batt_custom_dispatch_30min.csv rename to test/input_cases/custom_generation_data/batt_custom_dispatch_30min.csv diff --git a/test/input_cases/generic_system_data/batt_custom_dispatch_60min.csv b/test/input_cases/custom_generation_data/batt_custom_dispatch_60min.csv similarity index 100% rename from test/input_cases/generic_system_data/batt_custom_dispatch_60min.csv rename to test/input_cases/custom_generation_data/batt_custom_dispatch_60min.csv diff --git a/test/input_cases/generic_system_data/cp_variable_amount.csv b/test/input_cases/custom_generation_data/cp_variable_amount.csv similarity index 100% rename from test/input_cases/generic_system_data/cp_variable_amount.csv rename to test/input_cases/custom_generation_data/cp_variable_amount.csv diff --git a/test/input_cases/generic_system_data/cp_variable_percent_nameplate.csv b/test/input_cases/custom_generation_data/cp_variable_percent_nameplate.csv similarity index 100% rename from test/input_cases/generic_system_data/cp_variable_percent_nameplate.csv rename to test/input_cases/custom_generation_data/cp_variable_percent_nameplate.csv diff --git a/test/input_cases/generic_system_data/curtailment_30min_0percent.csv b/test/input_cases/custom_generation_data/curtailment_30min_0percent.csv similarity index 100% rename from test/input_cases/generic_system_data/curtailment_30min_0percent.csv rename to test/input_cases/custom_generation_data/curtailment_30min_0percent.csv diff --git a/test/input_cases/generic_system_data/curtailment_30min_50percent.csv b/test/input_cases/custom_generation_data/curtailment_30min_50percent.csv similarity index 100% rename from test/input_cases/generic_system_data/curtailment_30min_50percent.csv rename to test/input_cases/custom_generation_data/curtailment_30min_50percent.csv diff --git a/test/input_cases/generic_system_data/dispatch_factors_ts.csv b/test/input_cases/custom_generation_data/dispatch_factors_ts.csv similarity index 100% rename from test/input_cases/generic_system_data/dispatch_factors_ts.csv rename to test/input_cases/custom_generation_data/dispatch_factors_ts.csv diff --git a/test/input_cases/generic_system_data/energy_output_array.csv b/test/input_cases/custom_generation_data/energy_output_array.csv similarity index 100% rename from test/input_cases/generic_system_data/energy_output_array.csv rename to test/input_cases/custom_generation_data/energy_output_array.csv diff --git a/test/input_cases/generic_system_data/energy_output_array_30min-2yr.csv b/test/input_cases/custom_generation_data/energy_output_array_30min-2yr.csv similarity index 100% rename from test/input_cases/generic_system_data/energy_output_array_30min-2yr.csv rename to test/input_cases/custom_generation_data/energy_output_array_30min-2yr.csv diff --git a/test/input_cases/generic_system_data/energy_output_array_30min.csv b/test/input_cases/custom_generation_data/energy_output_array_30min.csv similarity index 100% rename from test/input_cases/generic_system_data/energy_output_array_30min.csv rename to test/input_cases/custom_generation_data/energy_output_array_30min.csv diff --git a/test/input_cases/generic_system_data/energy_output_array_30min.xlsx b/test/input_cases/custom_generation_data/energy_output_array_30min.xlsx similarity index 100% rename from test/input_cases/generic_system_data/energy_output_array_30min.xlsx rename to test/input_cases/custom_generation_data/energy_output_array_30min.xlsx diff --git a/test/input_cases/generic_system_data/energy_output_array_60min.csv b/test/input_cases/custom_generation_data/energy_output_array_60min.csv similarity index 100% rename from test/input_cases/generic_system_data/energy_output_array_60min.csv rename to test/input_cases/custom_generation_data/energy_output_array_60min.csv diff --git a/test/input_cases/generic_system_data/generic.sam b/test/input_cases/custom_generation_data/generic.sam similarity index 100% rename from test/input_cases/generic_system_data/generic.sam rename to test/input_cases/custom_generation_data/generic.sam diff --git a/test/input_cases/generic_system_data/load.csv b/test/input_cases/custom_generation_data/load.csv similarity index 100% rename from test/input_cases/generic_system_data/load.csv rename to test/input_cases/custom_generation_data/load.csv diff --git a/test/input_cases/generic_system_data/load_30min.csv b/test/input_cases/custom_generation_data/load_30min.csv similarity index 100% rename from test/input_cases/generic_system_data/load_30min.csv rename to test/input_cases/custom_generation_data/load_30min.csv diff --git a/test/input_cases/generic_system_data/load_60min.csv b/test/input_cases/custom_generation_data/load_60min.csv similarity index 100% rename from test/input_cases/generic_system_data/load_60min.csv rename to test/input_cases/custom_generation_data/load_60min.csv diff --git a/test/input_cases/generic_system_data/ur_ts_sell_rate.csv b/test/input_cases/custom_generation_data/ur_ts_sell_rate.csv similarity index 100% rename from test/input_cases/generic_system_data/ur_ts_sell_rate.csv rename to test/input_cases/custom_generation_data/ur_ts_sell_rate.csv diff --git a/test/input_cases/generic_common_data.h b/test/input_cases/generic_common_data.h index 0db351ac9..572059356 100644 --- a/test/input_cases/generic_common_data.h +++ b/test/input_cases/generic_common_data.h @@ -31,13 +31,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _GENERIC_COMMON_DATA_H_ -#define _GENERIC_COMMON_DATA_H_ +#ifndef _CUSTOMGENERATION_COMMON_DATA_H_ +#define _CUSTOMGENERATION_COMMON_DATA_H_ #include #include "code_generator_utilities.h" -namespace generictest { +namespace customgenerationtest { char load_profile_path_60min[256]; char load_profile_path_30min[256]; char gen_path_60min[256]; @@ -50,20 +50,20 @@ namespace generictest { char temperature_path_30min[256]; - int n1 = sprintf(load_profile_path_60min, "%s/test/input_cases/generic_system_data/load_60min.csv",SSCDIR); - int n2 = sprintf(load_profile_path_30min, "%s/test/input_cases/generic_system_data/load_30min.csv",SSCDIR); - int n3 = sprintf(gen_path_60min, "%s/test/input_cases/generic_system_data/energy_output_array_60min.csv",SSCDIR); - int n4 = sprintf(gen_path_30min, "%s/test/input_cases/generic_system_data/energy_output_array_30min.csv",SSCDIR); - int n5 = sprintf(batt_dispatch_path_30min, "%s/test/input_cases/generic_system_data/batt_custom_dispatch_30min.csv",SSCDIR); - int n6 = sprintf(batt_dispatch_path_60min, "%s/test/input_cases/generic_system_data/batt_custom_dispatch_60min.csv",SSCDIR); - int n7 = sprintf(dispatch_factors_unused, "%s/test/input_cases/generic_system_data/dispatch_factors_ts.csv",SSCDIR); - int n8 = sprintf(sell_rate_unused, "%s/test/input_cases/generic_system_data/ur_ts_sell_rate.csv",SSCDIR); + int n1 = sprintf(load_profile_path_60min, "%s/test/input_cases/custom_generation_profile_data/load_60min.csv",SSCDIR); + int n2 = sprintf(load_profile_path_30min, "%s/test/input_cases/custom_generation_profile_data/load_30min.csv",SSCDIR); + int n3 = sprintf(gen_path_60min, "%s/test/input_cases/custom_generation_profile_data/energy_output_array_60min.csv",SSCDIR); + int n4 = sprintf(gen_path_30min, "%s/test/input_cases/custom_generation_profile_data/energy_output_array_30min.csv",SSCDIR); + int n5 = sprintf(batt_dispatch_path_30min, "%s/test/input_cases/custom_generation_profile_data/batt_custom_dispatch_30min.csv",SSCDIR); + int n6 = sprintf(batt_dispatch_path_60min, "%s/test/input_cases/custom_generation_profile_data/batt_custom_dispatch_60min.csv",SSCDIR); + int n7 = sprintf(dispatch_factors_unused, "%s/test/input_cases/custom_generation_profile_data/dispatch_factors_ts.csv",SSCDIR); + int n8 = sprintf(sell_rate_unused, "%s/test/input_cases/custom_generation_profile_data/ur_ts_sell_rate.csv",SSCDIR); int n9 = sprintf(temperature_path, "%s/test/input_cases/battery_data/batt_room_temperature_celsius_60min.csv",SSCDIR); int n10 = sprintf(temperature_path_30min, "%s/test/input_cases/battery_data/batt_room_temperature_celsius_30min.csv",SSCDIR); } -void generic_singleowner_battery_60min(ssc_data_t &data) +void custom_generation_singleowner_battery_60min(ssc_data_t &data) { ssc_data_set_number( data, "spec_mode", 1 ); ssc_data_set_number( data, "derate", 0 ); @@ -71,7 +71,7 @@ void generic_singleowner_battery_60min(ssc_data_t &data) ssc_data_set_number( data, "user_capacity_factor", 43.599998474121094 ); ssc_data_set_number( data, "heat_rate", 0 ); ssc_data_set_number( data, "conv_eff", 0 ); - set_array( data, "energy_output_array", generictest::gen_path_60min, 8760); + set_array( data, "energy_output_array", customgenerationtest::gen_path_60min, 8760); ssc_data_set_number( data, "system_use_lifetime_output", 0 ); ssc_data_set_number( data, "analysis_period", 25 ); ssc_number_t p_generic_degradation[1] ={ 0 }; @@ -151,7 +151,7 @@ void generic_singleowner_battery_60min(ssc_data_t &data) ssc_data_set_number( data, "batt_surface_area", 2694 ); ssc_data_set_number( data, "batt_Cp", 1004 ); ssc_data_set_number( data, "batt_h_to_ambient", 20 ); - set_array(data, "batt_room_temperature_celsius", generictest::temperature_path, 8760); + set_array(data, "batt_room_temperature_celsius", customgenerationtest::temperature_path, 8760); ssc_number_t p_cap_vs_temp[8] ={ -10, 60, 0, 80, 25, 100, 40, 100 }; ssc_data_set_matrix( data, "cap_vs_temp", p_cap_vs_temp, 4, 2 ); ssc_number_t p_dispatch_manual_charge[6] ={ 1, 1, 1, 0, 0, 0 }; @@ -168,7 +168,7 @@ void generic_singleowner_battery_60min(ssc_data_t &data) ssc_data_set_matrix( data, "dispatch_manual_sched", p_dispatch_manual_sched, 12, 24 ); ssc_number_t p_dispatch_manual_sched_weekend[288] ={ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1 }; ssc_data_set_matrix( data, "dispatch_manual_sched_weekend", p_dispatch_manual_sched_weekend, 12, 24 ); - set_array( data, "batt_custom_dispatch", generictest::batt_dispatch_path_60min, 8760); + set_array( data, "batt_custom_dispatch", customgenerationtest::batt_dispatch_path_60min, 8760); ssc_data_set_number( data, "batt_dispatch_choice", 3 ); ssc_number_t p_batt_pv_clipping_forecast[1] ={ 0 }; ssc_data_set_array( data, "batt_pv_clipping_forecast", p_batt_pv_clipping_forecast, 1 ); @@ -351,7 +351,7 @@ void generic_singleowner_battery_60min(ssc_data_t &data) ssc_data_set_number( data, "loan_moratorium", 0 ); ssc_data_set_number( data, "system_use_recapitalization", 0 ); ssc_data_set_number( data, "ppa_multiplier_model", 0 ); - set_array( data, "dispatch_factors_ts", generictest::dispatch_factors_unused, 8147); + set_array( data, "dispatch_factors_ts", customgenerationtest::dispatch_factors_unused, 8147); ssc_number_t p_dispatch_tod_factors[9] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }; ssc_data_set_array(data, "dispatch_tod_factors", p_dispatch_tod_factors, 9); ssc_data_set_number( data, "total_installed_cost", 1554456064 ); @@ -431,7 +431,7 @@ void generic_singleowner_battery_60min(ssc_data_t &data) ssc_data_set_number( data, "batt_replacement_cost_escal", 0 ); } -void generic_commerical_battery_60min(ssc_data_t &data) +void custom_generation_commerical_battery_60min(ssc_data_t &data) { ssc_data_set_number(data, "spec_mode", 1); ssc_data_set_number(data, "derate", 4); @@ -439,7 +439,7 @@ void generic_commerical_battery_60min(ssc_data_t &data) ssc_data_set_number(data, "user_capacity_factor", 43.599998474121094); ssc_data_set_number(data, "heat_rate", 10); ssc_data_set_number(data, "conv_eff", 34.118049621582031); - set_array(data, "energy_output_array", generictest::gen_path_60min, 8760); + set_array(data, "energy_output_array", customgenerationtest::gen_path_60min, 8760); ssc_data_set_number(data, "system_use_lifetime_output", 0); ssc_data_set_number(data, "analysis_period", 25); ssc_number_t p_generic_degradation[1] = { 0 }; @@ -448,7 +448,7 @@ void generic_commerical_battery_60min(ssc_data_t &data) ssc_data_set_number(data, "adjust_constant", 0.0); ssc_data_set_number(data, "en_batt", 1); - set_array(data, "load", generictest::load_profile_path_60min, 8760); + set_array(data, "load", customgenerationtest::load_profile_path_60min, 8760); ssc_data_set_number(data, "batt_replacement_option", 0); ssc_data_set_number(data, "batt_chem", 1); ssc_data_set_number(data, "batt_ac_or_dc", 1); @@ -520,7 +520,7 @@ void generic_commerical_battery_60min(ssc_data_t &data) ssc_data_set_number(data, "batt_surface_area", 2.05); ssc_data_set_number(data, "batt_Cp", 1000); ssc_data_set_number(data, "batt_h_to_ambient", 20); - set_array(data, "batt_room_temperature_celsius", generictest::temperature_path, 8760); + set_array(data, "batt_room_temperature_celsius", customgenerationtest::temperature_path, 8760); ssc_number_t p_cap_vs_temp[8] = { -15, 65, 0, 85, 25, 100, 40, 104 }; ssc_data_set_matrix(data, "cap_vs_temp", p_cap_vs_temp, 4, 2); ssc_number_t p_dispatch_manual_charge[6] = { 1, 1, 1, 0, 0, 0 }; @@ -544,7 +544,7 @@ void generic_commerical_battery_60min(ssc_data_t &data) ssc_number_t p_batt_target_power_monthly[1] = { 0 }; ssc_data_set_array(data, "batt_target_power_monthly", p_batt_target_power_monthly, 1); ssc_data_set_number(data, "batt_target_choice", 0); - set_array(data, "batt_custom_dispatch", generictest::batt_dispatch_path_60min, 8760); + set_array(data, "batt_custom_dispatch", customgenerationtest::batt_dispatch_path_60min, 8760); ssc_data_set_number(data, "batt_dispatch_choice", 3); ssc_data_set_number(data, "batt_dispatch_auto_can_gridcharge", 0); ssc_data_set_number(data, "batt_dispatch_auto_can_charge", 1); @@ -570,7 +570,7 @@ void generic_commerical_battery_60min(ssc_data_t &data) ssc_data_set_number(data, "ur_monthly_min_charge", 0); ssc_data_set_number(data, "ur_annual_min_charge", 0); ssc_data_set_number(data, "ur_en_ts_sell_rate", 0); - set_array(data, "ur_ts_sell_rate", generictest::sell_rate_unused, 8760); + set_array(data, "ur_ts_sell_rate", customgenerationtest::sell_rate_unused, 8760); ssc_data_set_number(data, "ur_dc_enable", 1); ssc_number_t p_ur_dc_sched_weekday[288] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; ssc_data_set_matrix(data, "ur_dc_sched_weekday", p_ur_dc_sched_weekday, 12, 24); diff --git a/test/input_cases/grid_common_data.h b/test/input_cases/grid_common_data.h index 5dbe072a1..4c394c6e0 100644 --- a/test/input_cases/grid_common_data.h +++ b/test/input_cases/grid_common_data.h @@ -46,11 +46,11 @@ namespace { char gen_path_grid_30_2yr[256]; char grid_curtailment_default_MW[256]; - int nfc1 = sprintf(gen_path_grid, "%s/test/input_cases/generic_system_data/energy_output_array.csv", SSCDIR); + int nfc1 = sprintf(gen_path_grid, "%s/test/input_cases/custom_generation_data/energy_output_array.csv", SSCDIR); int nfc2 = sprintf(load_profile_path_grid, "%s/test/input_cases/general_data/commercial_load.csv", SSCDIR); - int nfc3 = sprintf(gen_path_grid_30, "%s/test/input_cases/generic_system_data/energy_output_array_30min.csv", SSCDIR); - int nfc4 = sprintf(load_profile_path_grid_30, "%s/test/input_cases/generic_system_data/load_30min.csv", SSCDIR); - int nfc5 = sprintf(gen_path_grid_30_2yr, "%s/test/input_cases/generic_system_data/energy_output_array_30min-2yr.csv", SSCDIR); + int nfc3 = sprintf(gen_path_grid_30, "%s/test/input_cases/custom_generation_data/energy_output_array_30min.csv", SSCDIR); + int nfc4 = sprintf(load_profile_path_grid_30, "%s/test/input_cases/custom_generation_data/load_30min.csv", SSCDIR); + int nfc5 = sprintf(gen_path_grid_30_2yr, "%s/test/input_cases/custom_generation_data/energy_output_array_30min-2yr.csv", SSCDIR); int nfc6 = sprintf(grid_curtailment_default_MW, "%s/test/input_cases/general_data/grid_curtailment_default_MW.csv", SSCDIR); } diff --git a/test/ssc_test/cmod_custom_generation_test.cpp b/test/ssc_test/cmod_custom_generation_test.cpp new file mode 100644 index 000000000..f7cd759cf --- /dev/null +++ b/test/ssc_test/cmod_custom_generation_test.cpp @@ -0,0 +1,139 @@ +/* +BSD 3-Clause License + +Copyright (c) Alliance for Sustainable Energy, LLC. See also https://github.com/NREL/ssc/blob/develop/LICENSE +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "cmod_custom_generation_test.h" + +/// Test Custom Generation with Battery for SingleOwner PPA +TEST_F(CMCustomGeneration, SingleOwnerWithBattery_cmod_generic) { + + generic_singleowner_battery_60min(data); + + // Test different dispatch strategies + std::vector dispatch_options{ 0,2,3 }; + + // Run with hourly data + for (size_t i = 0; i < dispatch_options.size(); i++) { + ssc_data_set_number(data, "batt_dispatch_choice", (ssc_number_t)dispatch_options[i]); + EXPECT_FALSE(run_module(data, "custom_generation")); + EXPECT_FALSE(run_module(data, "battery")); + EXPECT_FALSE(run_module(data, "singleowner")); + } + + // Run with subhourly data + set_array(data, "energy_output_array", generictest::gen_path_30min, 8760 * 2); + set_array(data, "batt_custom_dispatch", generictest::batt_dispatch_path_30min, 8760 * 2); + set_array(data, "batt_room_temperature_celsius", generictest::temperature_path_30min, 8760 * 2); + for (size_t i = 0; i < dispatch_options.size(); i++) { + ssc_data_set_number(data, "batt_dispatch_choice", (ssc_number_t)dispatch_options[i]); + EXPECT_FALSE(run_module(data, "custom_generation")); + EXPECT_FALSE(run_module(data, "battery")); + EXPECT_FALSE(run_module(data, "singleowner")); + } + + // Test with incorrect combo of data sizes + ssc_data_set_number(data, "batt_dispatch_choice", 3); + set_array(data, "batt_custom_dispatch", generictest::batt_dispatch_path_30min, 8760*2); // 8760 or 8760 * 3 fails with execution error on Linux and windows + EXPECT_FALSE(run_module(data, "custom_generation")); + EXPECT_FALSE(run_module(data, "battery")); +} + +/// Test Generic System with Battery for various timesteps +TEST_F(CMCustomGeneration, CommercialWithBattery_cmod_generic) { + + generic_commerical_battery_60min(data); + + // Test different dispatch strategies + std::vector dispatch_options{ 0,2,3 }; + + // Run with hourly data, with and without lifetime + for (size_t l = 0; l < 2; l++) { + ssc_data_set_number(data, "system_use_lifetime_output", l); + for (size_t i = 0; i < dispatch_options.size(); i++) { + ssc_data_set_number(data, "batt_dispatch_choice", (ssc_number_t)dispatch_options[i]); + EXPECT_FALSE(run_module(data, "custom_generation")); + EXPECT_FALSE(run_module(data, "battery")); + EXPECT_FALSE(run_module(data, "utilityrate5")); + EXPECT_FALSE(run_module(data, "cashloan")); + } + } + + // Run with subhourly data + set_array(data, "energy_output_array", generictest::gen_path_30min, 8760 * 2); + set_array(data, "batt_custom_dispatch", generictest::batt_dispatch_path_30min, 8760 * 2); + set_array(data, "batt_room_temperature_celsius", generictest::temperature_path_30min, 8760 * 2); + set_array(data, "load", generictest::load_profile_path_30min, 8760 * 2); + + // With and without lifetime + for (size_t l = 0; l < 2; l++) { + ssc_data_set_number(data, "system_use_lifetime_output", l); + for (size_t i = 0; i < dispatch_options.size(); i++) { + ssc_data_set_number(data, "batt_dispatch_choice", (ssc_number_t)dispatch_options[i]); + EXPECT_FALSE(run_module(data, "custom_generation")); + EXPECT_FALSE(run_module(data, "battery")); + EXPECT_FALSE(run_module(data, "utilityrate5")); + EXPECT_FALSE(run_module(data, "cashloan")); + } + } + + // Test with hourly load, subhourly gen + ssc_data_set_number(data, "batt_dispatch_choice", 3); + set_array(data, "batt_custom_dispatch", generictest::batt_dispatch_path_30min, 8760 * 2); + set_array(data, "energy_output_array", generictest::gen_path_30min, 2*8760); + set_array(data, "batt_room_temperature_celsius", generictest::temperature_path_30min, 8760 * 2); + set_array(data, "load", generictest::load_profile_path_60min, 8760); + + for (size_t l = 0; l < 2; l++) { + ssc_data_set_number(data, "system_use_lifetime_output", l); + EXPECT_FALSE(run_module(data, "custom_generation")); + EXPECT_FALSE(run_module(data, "battery")); + } +} + +/* +Doesn't work to to outdated exeception handling methods in SSC which can not be +handled robustly in a cross-platform environment +https://docs.microsoft.com/en-us/cpp/cpp/errors-and-exception-handling-modern-cpp?view=vs-2017#c-exceptions-versus-windows-seh-exceptions +*/ +/* +TEST_F(CMCustomGeneration, CommericalWithBatteryWrongSizes) +{ + // Test with hourly gen, subhourly load, should fail everywhere + generic_commerical_battery_60min(data); + set_array(data, "load", generictest::load_profile_path_30min, 2 * 8760); + + EXPECT_TRUE(run_module(data, "generic_system")); + EXPECT_TRUE(run_module(data, "battery")); +} +*/ diff --git a/test/ssc_test/cmod_custom_generation_test.h b/test/ssc_test/cmod_custom_generation_test.h new file mode 100644 index 000000000..03a25db76 --- /dev/null +++ b/test/ssc_test/cmod_custom_generation_test.h @@ -0,0 +1,86 @@ +/* +BSD 3-Clause License + +Copyright (c) Alliance for Sustainable Energy, LLC. See also https://github.com/NREL/ssc/blob/develop/LICENSE +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#ifndef _CMOD_GENERIC_TEST_H_ +#define _CMOD_GENERIC_TEST_H_ + +#include +#include + +#include "core.h" +#include "sscapi.h" + +#include "vartab.h" +#include "../ssc/common.h" +#include "../input_cases/code_generator_utilities.h" +#include "../input_cases/generic_common_data.h" + +/** + * CMFuelCell tests the cmod_fuelcell using the SAM code generator to generate data + * Eventually a method can be written to write this data to a vartable so that lower-level methods of pvsamv1 can be tested + * For now, this uses the SSCAPI interfaces to run the compute module and compare results + */ +class CMCustomGeneration : public ::testing::Test { + +public: + + ssc_data_t data; + ssc_number_t calculated_value; + ssc_number_t * calculated_array; + double m_error_tolerance_hi = 1.0; + double m_error_tolerance_lo = 0.1; + + void SetUp() + { + data = ssc_data_create(); + } + void TearDown() { + if (data) { + ssc_data_free(data); + data = nullptr; + } + } + void SetCalculated(std::string name) + { + ssc_data_get_number(data, const_cast(name.c_str()), &calculated_value); + } + // apparently memory of the array is managed internally to the sscapi. + void SetCalculatedArray(std::string name) + { + int n; + calculated_array = ssc_data_get_array(data, const_cast(name.c_str()), &n); + } +}; + +#endif diff --git a/test/ssc_test/cmod_generic_test.cpp b/test/ssc_test/cmod_generic_test.cpp index 344479c0d..42aae30c0 100644 --- a/test/ssc_test/cmod_generic_test.cpp +++ b/test/ssc_test/cmod_generic_test.cpp @@ -33,12 +33,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -#include "cmod_generic_test.h" +#include "cmod_custom_generation_test.h" /// Test Generic System with Battery for SingleOwner PPA -TEST_F(CMGeneric, SingleOwnerWithBattery_cmod_generic) { +TEST_F(CMCustomGeneration, SingleOwnerWithBattery_cmod_custom_generation) { - generic_singleowner_battery_60min(data); + custom_generation_singleowner_battery_60min(data); // Test different dispatch strategies std::vector dispatch_options{ 0,2,3 }; @@ -52,9 +52,9 @@ TEST_F(CMGeneric, SingleOwnerWithBattery_cmod_generic) { } // Run with subhourly data - set_array(data, "energy_output_array", generictest::gen_path_30min, 8760 * 2); - set_array(data, "batt_custom_dispatch", generictest::batt_dispatch_path_30min, 8760 * 2); - set_array(data, "batt_room_temperature_celsius", generictest::temperature_path_30min, 8760 * 2); + set_array(data, "energy_output_array", customgenerationtest::gen_path_30min, 8760 * 2); + set_array(data, "batt_custom_dispatch", customgenerationtest::batt_dispatch_path_30min, 8760 * 2); + set_array(data, "batt_room_temperature_celsius", customgenerationtest::temperature_path_30min, 8760 * 2); for (size_t i = 0; i < dispatch_options.size(); i++) { ssc_data_set_number(data, "batt_dispatch_choice", (ssc_number_t)dispatch_options[i]); EXPECT_FALSE(run_module(data, "custom_generation")); @@ -64,15 +64,15 @@ TEST_F(CMGeneric, SingleOwnerWithBattery_cmod_generic) { // Test with incorrect combo of data sizes ssc_data_set_number(data, "batt_dispatch_choice", 3); - set_array(data, "batt_custom_dispatch", generictest::batt_dispatch_path_30min, 8760*2); // 8760 or 8760 * 3 fails with execution error on Linux and windows + set_array(data, "batt_custom_dispatch", customgenerationtest::batt_dispatch_path_30min, 8760*2); // 8760 or 8760 * 3 fails with execution error on Linux and windows EXPECT_FALSE(run_module(data, "custom_generation")); EXPECT_FALSE(run_module(data, "battery")); } -/// Test Generic System with Battery for various timesteps -TEST_F(CMGeneric, CommercialWithBattery_cmod_generic) { +/// Test CustomGeneratoin System with Battery for various timesteps +TEST_F(CMCustomGeneration, CommercialWithBattery_cmod_custom_generation) { - generic_commerical_battery_60min(data); + custom_generation_commerical_battery_60min(data); // Test different dispatch strategies std::vector dispatch_options{ 0,2,3 }; @@ -90,10 +90,10 @@ TEST_F(CMGeneric, CommercialWithBattery_cmod_generic) { } // Run with subhourly data - set_array(data, "energy_output_array", generictest::gen_path_30min, 8760 * 2); - set_array(data, "batt_custom_dispatch", generictest::batt_dispatch_path_30min, 8760 * 2); - set_array(data, "batt_room_temperature_celsius", generictest::temperature_path_30min, 8760 * 2); - set_array(data, "load", generictest::load_profile_path_30min, 8760 * 2); + set_array(data, "energy_output_array", customgenerationtest::gen_path_30min, 8760 * 2); + set_array(data, "batt_custom_dispatch", customgenerationtest::batt_dispatch_path_30min, 8760 * 2); + set_array(data, "batt_room_temperature_celsius", customgenerationtest::temperature_path_30min, 8760 * 2); + set_array(data, "load", customgenerationtest::load_profile_path_30min, 8760 * 2); // With and without lifetime for (size_t l = 0; l < 2; l++) { @@ -109,10 +109,10 @@ TEST_F(CMGeneric, CommercialWithBattery_cmod_generic) { // Test with hourly load, subhourly gen ssc_data_set_number(data, "batt_dispatch_choice", 3); - set_array(data, "batt_custom_dispatch", generictest::batt_dispatch_path_30min, 8760 * 2); - set_array(data, "energy_output_array", generictest::gen_path_30min, 2*8760); - set_array(data, "batt_room_temperature_celsius", generictest::temperature_path_30min, 8760 * 2); - set_array(data, "load", generictest::load_profile_path_60min, 8760); + set_array(data, "batt_custom_dispatch", customgenerationtest::batt_dispatch_path_30min, 8760 * 2); + set_array(data, "energy_output_array", customgenerationtest::gen_path_30min, 2*8760); + set_array(data, "batt_room_temperature_celsius", customgenerationtest::temperature_path_30min, 8760 * 2); + set_array(data, "load", customgenerationtest::load_profile_path_60min, 8760); for (size_t l = 0; l < 2; l++) { ssc_data_set_number(data, "system_use_lifetime_output", l); @@ -127,13 +127,13 @@ handled robustly in a cross-platform environment https://docs.microsoft.com/en-us/cpp/cpp/errors-and-exception-handling-modern-cpp?view=vs-2017#c-exceptions-versus-windows-seh-exceptions */ /* -TEST_F(CMGeneric, CommericalWithBatteryWrongSizes) +TEST_F(CMCustomGeneration, CommericalWithBatteryWrongSizes) { // Test with hourly gen, subhourly load, should fail everywhere - generic_commerical_battery_60min(data); - set_array(data, "load", generictest::load_profile_path_30min, 2 * 8760); + custom_generation_commerical_battery_60min(data); + set_array(data, "load", customgenerationtest::load_profile_path_30min, 2 * 8760); - EXPECT_TRUE(run_module(data, "generic_system")); + EXPECT_TRUE(run_module(data, "custom_generation_system")); EXPECT_TRUE(run_module(data, "battery")); } */ diff --git a/test/ssc_test/cmod_generic_test.h b/test/ssc_test/cmod_generic_test.h index 2571f6e0c..cdc25d43f 100644 --- a/test/ssc_test/cmod_generic_test.h +++ b/test/ssc_test/cmod_generic_test.h @@ -32,8 +32,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#ifndef _CMOD_GENERIC_TEST_H_ -#define _CMOD_GENERIC_TEST_H_ +#ifndef _CMOD_CUSTOMGENERATION_TEST_H_ +#define _CMOD_CUSTOMGENERATION_TEST_H_ #include #include @@ -44,14 +44,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "vartab.h" #include "../ssc/common.h" #include "../input_cases/code_generator_utilities.h" -#include "../input_cases/generic_common_data.h" +#include "../input_cases/custom_generation_common_data.h" /** * CMFuelCell tests the cmod_fuelcell using the SAM code generator to generate data * Eventually a method can be written to write this data to a vartable so that lower-level methods of pvsamv1 can be tested * For now, this uses the SSCAPI interfaces to run the compute module and compare results */ -class CMGeneric : public ::testing::Test { +class CMCustomGeneration : public ::testing::Test { public: From 8b6ff0e2eb63374a8eb5976f11e54f88ebb8ab82 Mon Sep 17 00:00:00 2001 From: Matt Prilliman <54449384+mjprilliman@users.noreply.github.com> Date: Wed, 9 Oct 2024 09:26:20 -0500 Subject: [PATCH 3/8] Update naming from generic to custom generation --- ssc/cmod_custom_generation.cpp | 10 ++--- test/input_cases/biomass_common.h | 2 +- .../custom_generation_common_data.h | 44 +++++++++---------- test/ssc_test/cmod_custom_generation_test.cpp | 32 +++++++------- test/ssc_test/cmod_custom_generation_test.h | 6 +-- test/ssc_test/cmod_generic_test.cpp | 2 +- 6 files changed, 48 insertions(+), 48 deletions(-) diff --git a/ssc/cmod_custom_generation.cpp b/ssc/cmod_custom_generation.cpp index 36296b272..3e08747e9 100644 --- a/ssc/cmod_custom_generation.cpp +++ b/ssc/cmod_custom_generation.cpp @@ -48,7 +48,7 @@ static var_info _cm_vtab_custom_generation[] = { { SSC_INPUT, SSC_ARRAY, "energy_output_array", "Array of Energy Output Profile", "kW", "", "Plant", "spec_mode=1", "", "" }, // optional for lifetime analysis - { SSC_INPUT, SSC_NUMBER, "system_use_lifetime_output", "Generic lifetime simulation", "0/1", "", "Lifetime", "?=0", "INTEGER,MIN=0,MAX=1", "" }, + { SSC_INPUT, SSC_NUMBER, "system_use_lifetime_output", "Custom generation profile lifetime simulation", "0/1", "", "Lifetime", "?=0", "INTEGER,MIN=0,MAX=1", "" }, { SSC_INPUT, SSC_NUMBER, "analysis_period", "Lifetime analysis period", "years", "", "Lifetime", "system_use_lifetime_output=1", "", "" }, { SSC_INPUT, SSC_ARRAY, "generic_degradation", "Annual AC degradation", "%/year", "", "Lifetime", "system_use_lifetime_output=1", "", "" }, @@ -92,7 +92,7 @@ class cm_custom_generation : public compute_module // Warning workaround static bool is32BitLifetime = (__ARCHBITS__ == 32 && system_use_lifetime_output); if (is32BitLifetime) - throw exec_error( "generic", "Lifetime simulation of generic systems is only available in the 64 bit version of SAM."); + throw exec_error( "custom_generation", "Lifetime simulation of custom generation profile systems is only available in the 64 bit version of SAM."); // Lifetime setup ssc_number_t *enet = nullptr; @@ -120,7 +120,7 @@ class cm_custom_generation : public compute_module adjustment_factors haf(this, "adjust"); if (!haf.setup(nrec_load, nyears)) - throw exec_error("generic system", "failed to setup adjustment factors: " + haf.error()); + throw exec_error("custom_generation", "failed to setup adjustment factors: " + haf.error()); if (system_use_lifetime_output) { @@ -175,11 +175,11 @@ class cm_custom_generation : public compute_module size_t steps_per_hour_gen = nrec_gen / 8760; if (!enet_in) { - throw exec_error("generic", util::format("energy_output_array variable had no values.")); + throw exec_error("custom_generation", util::format("energy_output_array variable had no values.")); } if (nrec_gen < nrec_load) { - throw exec_error("generic", util::format("energy_output_array %d must be greater than or equal to load array %d", nrec_gen, nrec_load)); + throw exec_error("custom_generation", util::format("energy_output_array %d must be greater than or equal to load array %d", nrec_gen, nrec_load)); } else { nlifetime = nrec_gen * nyears; diff --git a/test/input_cases/biomass_common.h b/test/input_cases/biomass_common.h index b1602a806..61845c5c8 100644 --- a/test/input_cases/biomass_common.h +++ b/test/input_cases/biomass_common.h @@ -42,7 +42,7 @@ namespace biomass_test { char file_name[256]; int n1 = sprintf(file_name, "%s/test/input_cases/swh_residential_data/fargo_nd_46.9_-96.8_mts1_60_tmy.csv", SSCDIR); char dispatch_factors[256]; - int n2 = sprintf(dispatch_factors, "%s/test/input_cases/generic_system_data/dispatch_factors_ts.csv", SSCDIR); + int n2 = sprintf(dispatch_factors, "%s/test/input_cases/custom_generation_data/dispatch_factors_ts.csv", SSCDIR); } diff --git a/test/input_cases/custom_generation_common_data.h b/test/input_cases/custom_generation_common_data.h index 0db351ac9..2e84e744d 100644 --- a/test/input_cases/custom_generation_common_data.h +++ b/test/input_cases/custom_generation_common_data.h @@ -31,13 +31,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _GENERIC_COMMON_DATA_H_ -#define _GENERIC_COMMON_DATA_H_ +#ifndef _CUSTOMGENERATION_COMMON_DATA_H_ +#define _CUSTOMGENERATION_COMMON_DATA_H_ #include #include "code_generator_utilities.h" -namespace generictest { +namespace customgenerationtest { char load_profile_path_60min[256]; char load_profile_path_30min[256]; char gen_path_60min[256]; @@ -50,20 +50,20 @@ namespace generictest { char temperature_path_30min[256]; - int n1 = sprintf(load_profile_path_60min, "%s/test/input_cases/generic_system_data/load_60min.csv",SSCDIR); - int n2 = sprintf(load_profile_path_30min, "%s/test/input_cases/generic_system_data/load_30min.csv",SSCDIR); - int n3 = sprintf(gen_path_60min, "%s/test/input_cases/generic_system_data/energy_output_array_60min.csv",SSCDIR); - int n4 = sprintf(gen_path_30min, "%s/test/input_cases/generic_system_data/energy_output_array_30min.csv",SSCDIR); - int n5 = sprintf(batt_dispatch_path_30min, "%s/test/input_cases/generic_system_data/batt_custom_dispatch_30min.csv",SSCDIR); - int n6 = sprintf(batt_dispatch_path_60min, "%s/test/input_cases/generic_system_data/batt_custom_dispatch_60min.csv",SSCDIR); - int n7 = sprintf(dispatch_factors_unused, "%s/test/input_cases/generic_system_data/dispatch_factors_ts.csv",SSCDIR); - int n8 = sprintf(sell_rate_unused, "%s/test/input_cases/generic_system_data/ur_ts_sell_rate.csv",SSCDIR); + int n1 = sprintf(load_profile_path_60min, "%s/test/input_cases/custom_generation_data/load_60min.csv",SSCDIR); + int n2 = sprintf(load_profile_path_30min, "%s/test/input_cases/custom_generation_data/load_30min.csv",SSCDIR); + int n3 = sprintf(gen_path_60min, "%s/test/input_cases/custom_generation_data/energy_output_array_60min.csv",SSCDIR); + int n4 = sprintf(gen_path_30min, "%s/test/input_cases/custom_generation_data/energy_output_array_30min.csv",SSCDIR); + int n5 = sprintf(batt_dispatch_path_30min, "%s/test/input_cases/custom_generation_data/batt_custom_dispatch_30min.csv",SSCDIR); + int n6 = sprintf(batt_dispatch_path_60min, "%s/test/input_cases/custom_generation_data/batt_custom_dispatch_60min.csv",SSCDIR); + int n7 = sprintf(dispatch_factors_unused, "%s/test/input_cases/custom_generation_data/dispatch_factors_ts.csv",SSCDIR); + int n8 = sprintf(sell_rate_unused, "%s/test/input_cases/custom_generation_data/ur_ts_sell_rate.csv",SSCDIR); int n9 = sprintf(temperature_path, "%s/test/input_cases/battery_data/batt_room_temperature_celsius_60min.csv",SSCDIR); int n10 = sprintf(temperature_path_30min, "%s/test/input_cases/battery_data/batt_room_temperature_celsius_30min.csv",SSCDIR); } -void generic_singleowner_battery_60min(ssc_data_t &data) +void custom_generation_singleowner_battery_60min(ssc_data_t &data) { ssc_data_set_number( data, "spec_mode", 1 ); ssc_data_set_number( data, "derate", 0 ); @@ -71,7 +71,7 @@ void generic_singleowner_battery_60min(ssc_data_t &data) ssc_data_set_number( data, "user_capacity_factor", 43.599998474121094 ); ssc_data_set_number( data, "heat_rate", 0 ); ssc_data_set_number( data, "conv_eff", 0 ); - set_array( data, "energy_output_array", generictest::gen_path_60min, 8760); + set_array( data, "energy_output_array", customgenerationtest::gen_path_60min, 8760); ssc_data_set_number( data, "system_use_lifetime_output", 0 ); ssc_data_set_number( data, "analysis_period", 25 ); ssc_number_t p_generic_degradation[1] ={ 0 }; @@ -151,7 +151,7 @@ void generic_singleowner_battery_60min(ssc_data_t &data) ssc_data_set_number( data, "batt_surface_area", 2694 ); ssc_data_set_number( data, "batt_Cp", 1004 ); ssc_data_set_number( data, "batt_h_to_ambient", 20 ); - set_array(data, "batt_room_temperature_celsius", generictest::temperature_path, 8760); + set_array(data, "batt_room_temperature_celsius", customgenerationtest::temperature_path, 8760); ssc_number_t p_cap_vs_temp[8] ={ -10, 60, 0, 80, 25, 100, 40, 100 }; ssc_data_set_matrix( data, "cap_vs_temp", p_cap_vs_temp, 4, 2 ); ssc_number_t p_dispatch_manual_charge[6] ={ 1, 1, 1, 0, 0, 0 }; @@ -168,7 +168,7 @@ void generic_singleowner_battery_60min(ssc_data_t &data) ssc_data_set_matrix( data, "dispatch_manual_sched", p_dispatch_manual_sched, 12, 24 ); ssc_number_t p_dispatch_manual_sched_weekend[288] ={ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1 }; ssc_data_set_matrix( data, "dispatch_manual_sched_weekend", p_dispatch_manual_sched_weekend, 12, 24 ); - set_array( data, "batt_custom_dispatch", generictest::batt_dispatch_path_60min, 8760); + set_array( data, "batt_custom_dispatch", customgenerationtest::batt_dispatch_path_60min, 8760); ssc_data_set_number( data, "batt_dispatch_choice", 3 ); ssc_number_t p_batt_pv_clipping_forecast[1] ={ 0 }; ssc_data_set_array( data, "batt_pv_clipping_forecast", p_batt_pv_clipping_forecast, 1 ); @@ -351,7 +351,7 @@ void generic_singleowner_battery_60min(ssc_data_t &data) ssc_data_set_number( data, "loan_moratorium", 0 ); ssc_data_set_number( data, "system_use_recapitalization", 0 ); ssc_data_set_number( data, "ppa_multiplier_model", 0 ); - set_array( data, "dispatch_factors_ts", generictest::dispatch_factors_unused, 8147); + set_array( data, "dispatch_factors_ts", customgenerationtest::dispatch_factors_unused, 8147); ssc_number_t p_dispatch_tod_factors[9] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }; ssc_data_set_array(data, "dispatch_tod_factors", p_dispatch_tod_factors, 9); ssc_data_set_number( data, "total_installed_cost", 1554456064 ); @@ -431,7 +431,7 @@ void generic_singleowner_battery_60min(ssc_data_t &data) ssc_data_set_number( data, "batt_replacement_cost_escal", 0 ); } -void generic_commerical_battery_60min(ssc_data_t &data) +void custom_generation_commerical_battery_60min(ssc_data_t &data) { ssc_data_set_number(data, "spec_mode", 1); ssc_data_set_number(data, "derate", 4); @@ -439,7 +439,7 @@ void generic_commerical_battery_60min(ssc_data_t &data) ssc_data_set_number(data, "user_capacity_factor", 43.599998474121094); ssc_data_set_number(data, "heat_rate", 10); ssc_data_set_number(data, "conv_eff", 34.118049621582031); - set_array(data, "energy_output_array", generictest::gen_path_60min, 8760); + set_array(data, "energy_output_array", customgenerationtest::gen_path_60min, 8760); ssc_data_set_number(data, "system_use_lifetime_output", 0); ssc_data_set_number(data, "analysis_period", 25); ssc_number_t p_generic_degradation[1] = { 0 }; @@ -448,7 +448,7 @@ void generic_commerical_battery_60min(ssc_data_t &data) ssc_data_set_number(data, "adjust_constant", 0.0); ssc_data_set_number(data, "en_batt", 1); - set_array(data, "load", generictest::load_profile_path_60min, 8760); + set_array(data, "load", customgenerationtest::load_profile_path_60min, 8760); ssc_data_set_number(data, "batt_replacement_option", 0); ssc_data_set_number(data, "batt_chem", 1); ssc_data_set_number(data, "batt_ac_or_dc", 1); @@ -520,7 +520,7 @@ void generic_commerical_battery_60min(ssc_data_t &data) ssc_data_set_number(data, "batt_surface_area", 2.05); ssc_data_set_number(data, "batt_Cp", 1000); ssc_data_set_number(data, "batt_h_to_ambient", 20); - set_array(data, "batt_room_temperature_celsius", generictest::temperature_path, 8760); + set_array(data, "batt_room_temperature_celsius", customgenerationtest::temperature_path, 8760); ssc_number_t p_cap_vs_temp[8] = { -15, 65, 0, 85, 25, 100, 40, 104 }; ssc_data_set_matrix(data, "cap_vs_temp", p_cap_vs_temp, 4, 2); ssc_number_t p_dispatch_manual_charge[6] = { 1, 1, 1, 0, 0, 0 }; @@ -544,7 +544,7 @@ void generic_commerical_battery_60min(ssc_data_t &data) ssc_number_t p_batt_target_power_monthly[1] = { 0 }; ssc_data_set_array(data, "batt_target_power_monthly", p_batt_target_power_monthly, 1); ssc_data_set_number(data, "batt_target_choice", 0); - set_array(data, "batt_custom_dispatch", generictest::batt_dispatch_path_60min, 8760); + set_array(data, "batt_custom_dispatch", customgenerationtest::batt_dispatch_path_60min, 8760); ssc_data_set_number(data, "batt_dispatch_choice", 3); ssc_data_set_number(data, "batt_dispatch_auto_can_gridcharge", 0); ssc_data_set_number(data, "batt_dispatch_auto_can_charge", 1); @@ -570,7 +570,7 @@ void generic_commerical_battery_60min(ssc_data_t &data) ssc_data_set_number(data, "ur_monthly_min_charge", 0); ssc_data_set_number(data, "ur_annual_min_charge", 0); ssc_data_set_number(data, "ur_en_ts_sell_rate", 0); - set_array(data, "ur_ts_sell_rate", generictest::sell_rate_unused, 8760); + set_array(data, "ur_ts_sell_rate", customgenerationtest::sell_rate_unused, 8760); ssc_data_set_number(data, "ur_dc_enable", 1); ssc_number_t p_ur_dc_sched_weekday[288] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; ssc_data_set_matrix(data, "ur_dc_sched_weekday", p_ur_dc_sched_weekday, 12, 24); diff --git a/test/ssc_test/cmod_custom_generation_test.cpp b/test/ssc_test/cmod_custom_generation_test.cpp index f7cd759cf..603751e3a 100644 --- a/test/ssc_test/cmod_custom_generation_test.cpp +++ b/test/ssc_test/cmod_custom_generation_test.cpp @@ -36,9 +36,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "cmod_custom_generation_test.h" /// Test Custom Generation with Battery for SingleOwner PPA -TEST_F(CMCustomGeneration, SingleOwnerWithBattery_cmod_generic) { +TEST_F(CMCustomGeneration, SingleOwnerWithBattery_cmod_custom_generation) { - generic_singleowner_battery_60min(data); + custom_generation_singleowner_battery_60min(data); // Test different dispatch strategies std::vector dispatch_options{ 0,2,3 }; @@ -52,9 +52,9 @@ TEST_F(CMCustomGeneration, SingleOwnerWithBattery_cmod_generic) { } // Run with subhourly data - set_array(data, "energy_output_array", generictest::gen_path_30min, 8760 * 2); - set_array(data, "batt_custom_dispatch", generictest::batt_dispatch_path_30min, 8760 * 2); - set_array(data, "batt_room_temperature_celsius", generictest::temperature_path_30min, 8760 * 2); + set_array(data, "energy_output_array", customgenerationtest::gen_path_30min, 8760 * 2); + set_array(data, "batt_custom_dispatch", customgenerationtest::batt_dispatch_path_30min, 8760 * 2); + set_array(data, "batt_room_temperature_celsius", customgenerationtest::temperature_path_30min, 8760 * 2); for (size_t i = 0; i < dispatch_options.size(); i++) { ssc_data_set_number(data, "batt_dispatch_choice", (ssc_number_t)dispatch_options[i]); EXPECT_FALSE(run_module(data, "custom_generation")); @@ -64,7 +64,7 @@ TEST_F(CMCustomGeneration, SingleOwnerWithBattery_cmod_generic) { // Test with incorrect combo of data sizes ssc_data_set_number(data, "batt_dispatch_choice", 3); - set_array(data, "batt_custom_dispatch", generictest::batt_dispatch_path_30min, 8760*2); // 8760 or 8760 * 3 fails with execution error on Linux and windows + set_array(data, "batt_custom_dispatch", customgenerationtest::batt_dispatch_path_30min, 8760*2); // 8760 or 8760 * 3 fails with execution error on Linux and windows EXPECT_FALSE(run_module(data, "custom_generation")); EXPECT_FALSE(run_module(data, "battery")); } @@ -72,7 +72,7 @@ TEST_F(CMCustomGeneration, SingleOwnerWithBattery_cmod_generic) { /// Test Generic System with Battery for various timesteps TEST_F(CMCustomGeneration, CommercialWithBattery_cmod_generic) { - generic_commerical_battery_60min(data); + custom_generation_commerical_battery_60min(data); // Test different dispatch strategies std::vector dispatch_options{ 0,2,3 }; @@ -90,10 +90,10 @@ TEST_F(CMCustomGeneration, CommercialWithBattery_cmod_generic) { } // Run with subhourly data - set_array(data, "energy_output_array", generictest::gen_path_30min, 8760 * 2); - set_array(data, "batt_custom_dispatch", generictest::batt_dispatch_path_30min, 8760 * 2); - set_array(data, "batt_room_temperature_celsius", generictest::temperature_path_30min, 8760 * 2); - set_array(data, "load", generictest::load_profile_path_30min, 8760 * 2); + set_array(data, "energy_output_array", customgenerationtest::gen_path_30min, 8760 * 2); + set_array(data, "batt_custom_dispatch", customgenerationtest::batt_dispatch_path_30min, 8760 * 2); + set_array(data, "batt_room_temperature_celsius", customgenerationtest::temperature_path_30min, 8760 * 2); + set_array(data, "load", customgenerationtest::load_profile_path_30min, 8760 * 2); // With and without lifetime for (size_t l = 0; l < 2; l++) { @@ -109,10 +109,10 @@ TEST_F(CMCustomGeneration, CommercialWithBattery_cmod_generic) { // Test with hourly load, subhourly gen ssc_data_set_number(data, "batt_dispatch_choice", 3); - set_array(data, "batt_custom_dispatch", generictest::batt_dispatch_path_30min, 8760 * 2); - set_array(data, "energy_output_array", generictest::gen_path_30min, 2*8760); - set_array(data, "batt_room_temperature_celsius", generictest::temperature_path_30min, 8760 * 2); - set_array(data, "load", generictest::load_profile_path_60min, 8760); + set_array(data, "batt_custom_dispatch", customgenerationtest::batt_dispatch_path_30min, 8760 * 2); + set_array(data, "energy_output_array", customgenerationtest::gen_path_30min, 2*8760); + set_array(data, "batt_room_temperature_celsius", customgenerationtest::temperature_path_30min, 8760 * 2); + set_array(data, "load", customgenerationtest::load_profile_path_60min, 8760); for (size_t l = 0; l < 2; l++) { ssc_data_set_number(data, "system_use_lifetime_output", l); @@ -131,7 +131,7 @@ TEST_F(CMCustomGeneration, CommericalWithBatteryWrongSizes) { // Test with hourly gen, subhourly load, should fail everywhere generic_commerical_battery_60min(data); - set_array(data, "load", generictest::load_profile_path_30min, 2 * 8760); + set_array(data, "load", customgenerationtest::load_profile_path_30min, 2 * 8760); EXPECT_TRUE(run_module(data, "generic_system")); EXPECT_TRUE(run_module(data, "battery")); diff --git a/test/ssc_test/cmod_custom_generation_test.h b/test/ssc_test/cmod_custom_generation_test.h index 03a25db76..cdc25d43f 100644 --- a/test/ssc_test/cmod_custom_generation_test.h +++ b/test/ssc_test/cmod_custom_generation_test.h @@ -32,8 +32,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#ifndef _CMOD_GENERIC_TEST_H_ -#define _CMOD_GENERIC_TEST_H_ +#ifndef _CMOD_CUSTOMGENERATION_TEST_H_ +#define _CMOD_CUSTOMGENERATION_TEST_H_ #include #include @@ -44,7 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "vartab.h" #include "../ssc/common.h" #include "../input_cases/code_generator_utilities.h" -#include "../input_cases/generic_common_data.h" +#include "../input_cases/custom_generation_common_data.h" /** * CMFuelCell tests the cmod_fuelcell using the SAM code generator to generate data diff --git a/test/ssc_test/cmod_generic_test.cpp b/test/ssc_test/cmod_generic_test.cpp index 42aae30c0..4fd2272ff 100644 --- a/test/ssc_test/cmod_generic_test.cpp +++ b/test/ssc_test/cmod_generic_test.cpp @@ -35,7 +35,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "cmod_custom_generation_test.h" -/// Test Generic System with Battery for SingleOwner PPA +/// Test Custom Generation Profile with Battery for SingleOwner PPA TEST_F(CMCustomGeneration, SingleOwnerWithBattery_cmod_custom_generation) { custom_generation_singleowner_battery_60min(data); From 3e7af99b279d671bcf7961e578d5c263137e8cde Mon Sep 17 00:00:00 2001 From: Matt Prilliman <54449384+mjprilliman@users.noreply.github.com> Date: Wed, 9 Oct 2024 17:29:34 -0500 Subject: [PATCH 4/8] Update naming for tests --- test/ssc_test/cmod_cashloan_test.cpp | 8 ++++---- test/ssc_test/cmod_equpartflip_test.cpp | 4 ++-- test/ssc_test/cmod_host_developer_test.cpp | 4 ++-- test/ssc_test/cmod_hybrid_test.cpp | 2 +- test/ssc_test/cmod_lcoefcr_test.cpp | 2 +- test/ssc_test/cmod_levpartflip_test.cpp | 4 ++-- test/ssc_test/cmod_merchantplant_test.cpp | 6 +++--- test/ssc_test/cmod_saleleaseback_test.cpp | 4 ++-- test/ssc_test/cmod_singleowner_test.cpp | 4 ++-- test/ssc_test/cmod_thirdpartyownership_test.cpp | 4 ++-- 10 files changed, 21 insertions(+), 21 deletions(-) diff --git a/test/ssc_test/cmod_cashloan_test.cpp b/test/ssc_test/cmod_cashloan_test.cpp index b404e7295..4eb6d6380 100644 --- a/test/ssc_test/cmod_cashloan_test.cpp +++ b/test/ssc_test/cmod_cashloan_test.cpp @@ -166,7 +166,7 @@ TEST_F(CmodCashLoanTest, PVBatteryCommercial) { Test("cashloan", file_inputs, file_outputs, compare_number_variables, compare_array_variables); } -TEST_F(CmodCashLoanTest, GenericResidential) { +TEST_F(CmodCashLoanTest, CustomGenerationResidential) { std::string file_inputs = SSCDIR; file_inputs += "/test/input_json/FinancialModels/cashloan/2022.08.08_develop_branch_Generic_System_Residential_cmod_cashloan.json"; std::string file_outputs = SSCDIR; @@ -177,7 +177,7 @@ TEST_F(CmodCashLoanTest, GenericResidential) { Test("cashloan", file_inputs, file_outputs, compare_number_variables, compare_array_variables); } -TEST_F(CmodCashLoanTest, GenericCommercial) { +TEST_F(CmodCashLoanTest, CustomGenerationCommercial) { std::string file_inputs = SSCDIR; file_inputs += "/test/input_json/FinancialModels/cashloan/2022.08.08_develop_branch_Generic_System_Commercial_cmod_cashloan.json"; std::string file_outputs = SSCDIR; @@ -188,7 +188,7 @@ TEST_F(CmodCashLoanTest, GenericCommercial) { Test("cashloan", file_inputs, file_outputs, compare_number_variables, compare_array_variables); } -TEST_F(CmodCashLoanTest, GenericBatteryResidential) { +TEST_F(CmodCashLoanTest, CustomGenerationBatteryResidential) { std::string file_inputs = SSCDIR; file_inputs += "/test/input_json/FinancialModels/cashloan/2022.08.08_develop_branch_Generic_Battery_Residential_cmod_cashloan.json"; std::string file_outputs = SSCDIR; @@ -199,7 +199,7 @@ TEST_F(CmodCashLoanTest, GenericBatteryResidential) { Test("cashloan", file_inputs, file_outputs, compare_number_variables, compare_array_variables); } -TEST_F(CmodCashLoanTest, GenericBatteryCommercial) { +TEST_F(CmodCashLoanTest, CustomGenerationBatteryCommercial) { std::string file_inputs = SSCDIR; file_inputs += "/test/input_json/FinancialModels/cashloan/2022.08.08_develop_branch_Generic_Battery_Commercial_cmod_cashloan.json"; std::string file_outputs = SSCDIR; diff --git a/test/ssc_test/cmod_equpartflip_test.cpp b/test/ssc_test/cmod_equpartflip_test.cpp index a5113dade..fb47176f4 100644 --- a/test/ssc_test/cmod_equpartflip_test.cpp +++ b/test/ssc_test/cmod_equpartflip_test.cpp @@ -82,7 +82,7 @@ TEST_F(CmodAllEquityPartnershipFlipTest, PV) { } -TEST_F(CmodAllEquityPartnershipFlipTest, GenericBattery) { +TEST_F(CmodAllEquityPartnershipFlipTest, CustomGenerationBattery) { std::string file_inputs = SSCDIR; file_inputs += "/test/input_json/FinancialModels/equpartflip/2023.10.27_om-expense-cash-flow_Generic_Battery_All_Equity_Partnership_Flip_cmod_equpartflip.json"; std::string file_outputs = SSCDIR; @@ -104,7 +104,7 @@ TEST_F(CmodAllEquityPartnershipFlipTest, GenericCSP) { Test("equpartflip", file_inputs, file_outputs, compare_number_variables, compare_array_variables); } -TEST_F(CmodAllEquityPartnershipFlipTest, Generic) { +TEST_F(CmodAllEquityPartnershipFlipTest, CustomGeneration) { std::string file_inputs = SSCDIR; file_inputs += "/test/input_json/FinancialModels/equpartflip/2023.10.27_om-expense-cash-flow_Generic_System_All_Equity_Partnership_Flip_cmod_equpartflip.json"; std::string file_outputs = SSCDIR; diff --git a/test/ssc_test/cmod_host_developer_test.cpp b/test/ssc_test/cmod_host_developer_test.cpp index 6399dfd6d..d3f291168 100644 --- a/test/ssc_test/cmod_host_developer_test.cpp +++ b/test/ssc_test/cmod_host_developer_test.cpp @@ -148,7 +148,7 @@ TEST_F(CmodHostDeveloperTest, PVBattery) { } -TEST_F(CmodHostDeveloperTest, Generic) { +TEST_F(CmodHostDeveloperTest, CustomGeneration) { std::string file_inputs = SSCDIR; file_inputs += "/test/input_json/FinancialModels/host_developer/2023.10.27_om-expense-cash-flow_Generic_System_Host_Developer_cmod_host_developer.json"; std::string file_outputs = SSCDIR; @@ -160,7 +160,7 @@ TEST_F(CmodHostDeveloperTest, Generic) { } -TEST_F(CmodHostDeveloperTest, GenericBattery) { +TEST_F(CmodHostDeveloperTest, CustomGenerationBattery) { std::string file_inputs = SSCDIR; file_inputs += "/test/input_json/FinancialModels/host_developer/2023.10.27_om-expense-cash-flow_Generic_Battery_Host_Developer_cmod_host_developer.json"; std::string file_outputs = SSCDIR; diff --git a/test/ssc_test/cmod_hybrid_test.cpp b/test/ssc_test/cmod_hybrid_test.cpp index 17dd40043..85efc302d 100644 --- a/test/ssc_test/cmod_hybrid_test.cpp +++ b/test/ssc_test/cmod_hybrid_test.cpp @@ -153,7 +153,7 @@ TEST_F(CmodHybridTest, PVWattsv8WindBatteryHostDeveloper) { dat = nullptr; } -TEST_F(CmodHybridTest, GenericPVWattsWindFuelCellBatteryHybrid_SingleOwner) { +TEST_F(CmodHybridTest, CustomGenerationPVWattsWindFuelCellBatteryHybrid_SingleOwner) { char file_path[256]; int nfc1 = sprintf(file_path, "%s/test/input_json/hybrids/Generic PVWatts Wind FuelCell Battery Hybrid_Single Owner.json", SSCDIR); std::ifstream file(file_path); diff --git a/test/ssc_test/cmod_lcoefcr_test.cpp b/test/ssc_test/cmod_lcoefcr_test.cpp index b4bf37ae3..ddc6542b5 100644 --- a/test/ssc_test/cmod_lcoefcr_test.cpp +++ b/test/ssc_test/cmod_lcoefcr_test.cpp @@ -92,7 +92,7 @@ TEST_F(CmodLCOEFCRTest, GenericCSP) { Test("lcoefcr", file_inputs, file_outputs, compare_number_variables, compare_array_variables); } -TEST_F(CmodLCOEFCRTest, Generic) { +TEST_F(CmodLCOEFCRTest, CustomGeneration) { std::string file_inputs = SSCDIR; file_inputs += "/test/input_json/FinancialModels/lcoefcr/2022.08.08_develop_branch_Generic_System_LCOE_Calculator_cmod_lcoefcr.json"; std::string file_outputs = SSCDIR; diff --git a/test/ssc_test/cmod_levpartflip_test.cpp b/test/ssc_test/cmod_levpartflip_test.cpp index 6b549c9b2..72df4b4b2 100644 --- a/test/ssc_test/cmod_levpartflip_test.cpp +++ b/test/ssc_test/cmod_levpartflip_test.cpp @@ -82,7 +82,7 @@ TEST_F(CmodLeveragedPartnershipFlipTest, PV) { } -TEST_F(CmodLeveragedPartnershipFlipTest, GenericBattery) { +TEST_F(CmodLeveragedPartnershipFlipTest, CustomGenerationBattery) { std::string file_inputs = SSCDIR; file_inputs += "/test/input_json/FinancialModels/levpartflip/2023.10.27_om-expense-cash-flow_Generic_Battery_Leveraged_Partnership_Flip_cmod_levpartflip.json"; std::string file_outputs = SSCDIR; @@ -104,7 +104,7 @@ TEST_F(CmodLeveragedPartnershipFlipTest, GenericCSP) { Test("levpartflip", file_inputs, file_outputs, compare_number_variables, compare_array_variables); } -TEST_F(CmodLeveragedPartnershipFlipTest, Generic) { +TEST_F(CmodLeveragedPartnershipFlipTest, CustomGeneration) { std::string file_inputs = SSCDIR; file_inputs += "/test/input_json/FinancialModels/levpartflip/2023.10.27_om-expense-cash-flow_Generic_System_Leveraged_Partnership_Flip_cmod_levpartflip.json"; std::string file_outputs = SSCDIR; diff --git a/test/ssc_test/cmod_merchantplant_test.cpp b/test/ssc_test/cmod_merchantplant_test.cpp index 61e9aa08a..cdfff6d9d 100644 --- a/test/ssc_test/cmod_merchantplant_test.cpp +++ b/test/ssc_test/cmod_merchantplant_test.cpp @@ -82,7 +82,7 @@ TEST_F(CmodMerchantPlantTest, PV) { } -TEST_F(CmodMerchantPlantTest, GenericBattery) { +TEST_F(CmodMerchantPlantTest, CustomGenerationBattery) { std::string file_inputs = SSCDIR; file_inputs += "/test/input_json/FinancialModels/merchantplant/2022.08.08_develop_branch_Generic_Battery_Merchant_Plant_cmod_merchantplant.json"; std::string file_outputs = SSCDIR; @@ -93,7 +93,7 @@ TEST_F(CmodMerchantPlantTest, GenericBattery) { Test("merchantplant", file_inputs, file_outputs, compare_number_variables, compare_array_variables); } -TEST_F(CmodMerchantPlantTest, GenericBattery_LCOS) { +TEST_F(CmodMerchantPlantTest, CustomGenerationBattery_LCOS) { std::string file_inputs = SSCDIR; file_inputs += "/test/input_json/FinancialModels/merchantplant/2022.10.21_develop_branch_Generic_Battery_Merchant_Plant_cmod_merchantplant.json"; std::string file_outputs = SSCDIR; @@ -115,7 +115,7 @@ TEST_F(CmodMerchantPlantTest, GenericCSP) { Test("merchantplant", file_inputs, file_outputs, compare_number_variables, compare_array_variables); } -TEST_F(CmodMerchantPlantTest, Generic) { +TEST_F(CmodMerchantPlantTest, CustomGeneration) { std::string file_inputs = SSCDIR; file_inputs += "/test/input_json/FinancialModels/merchantplant/2022.08.08_develop_branch_Generic_System_Merchant_Plant_cmod_merchantplant.json"; std::string file_outputs = SSCDIR; diff --git a/test/ssc_test/cmod_saleleaseback_test.cpp b/test/ssc_test/cmod_saleleaseback_test.cpp index b95dbe078..d3a2a375b 100644 --- a/test/ssc_test/cmod_saleleaseback_test.cpp +++ b/test/ssc_test/cmod_saleleaseback_test.cpp @@ -82,7 +82,7 @@ TEST_F(CmodSaleLeasebackTest, PV) { } -TEST_F(CmodSaleLeasebackTest, GenericBattery) { +TEST_F(CmodSaleLeasebackTest, CustomGenerationBattery) { std::string file_inputs = SSCDIR; file_inputs += "/test/input_json/FinancialModels/saleleaseback/2023.10.27_om-expense-cash-flow_Generic_Battery_Sale_Leaseback_cmod_saleleaseback.json"; std::string file_outputs = SSCDIR; @@ -104,7 +104,7 @@ TEST_F(CmodSaleLeasebackTest, GenericCSP) { Test("saleleaseback", file_inputs, file_outputs, compare_number_variables, compare_array_variables); } -TEST_F(CmodSaleLeasebackTest, Generic) { +TEST_F(CmodSaleLeasebackTest, CustomGeneration) { std::string file_inputs = SSCDIR; file_inputs += "/test/input_json/FinancialModels/saleleaseback/2023.10.27_om-expense-cash-flow_Generic_System_Sale_Leaseback_cmod_saleleaseback.json"; std::string file_outputs = SSCDIR; diff --git a/test/ssc_test/cmod_singleowner_test.cpp b/test/ssc_test/cmod_singleowner_test.cpp index b070e2880..04ca430ad 100644 --- a/test/ssc_test/cmod_singleowner_test.cpp +++ b/test/ssc_test/cmod_singleowner_test.cpp @@ -125,7 +125,7 @@ TEST_F(CmodSingleOwnerTest, FuelCell) { Test("singleowner", file_inputs, file_outputs, compare_number_variables, compare_array_variables); } -TEST_F(CmodSingleOwnerTest, GenericBattery) { +TEST_F(CmodSingleOwnerTest, CustomGenerationBattery) { std::string file_inputs = SSCDIR; file_inputs += "/test/input_json/FinancialModels/singleowner/2022.08.08_develop_branch_Generic_Battery_Single_Owner_cmod_singleowner.json"; std::string file_outputs = SSCDIR; @@ -147,7 +147,7 @@ TEST_F(CmodSingleOwnerTest, GenericCSP) { Test("singleowner", file_inputs, file_outputs, compare_number_variables, compare_array_variables); } -TEST_F(CmodSingleOwnerTest, Generic) { +TEST_F(CmodSingleOwnerTest, CustomGeneration) { std::string file_inputs = SSCDIR; file_inputs += "/test/input_json/FinancialModels/singleowner/2022.08.08_develop_branch_Generic_System_Single_Owner_cmod_singleowner.json"; std::string file_outputs = SSCDIR; diff --git a/test/ssc_test/cmod_thirdpartyownership_test.cpp b/test/ssc_test/cmod_thirdpartyownership_test.cpp index 131968c88..dd2e314d4 100644 --- a/test/ssc_test/cmod_thirdpartyownership_test.cpp +++ b/test/ssc_test/cmod_thirdpartyownership_test.cpp @@ -82,7 +82,7 @@ TEST_F(CmodThirdPartyOwnershipTest, PVBattery) { } -TEST_F(CmodThirdPartyOwnershipTest, Generic) { +TEST_F(CmodThirdPartyOwnershipTest, CustomGeneration) { std::string file_inputs = SSCDIR; file_inputs += "/test/input_json/FinancialModels/thirdpartyownership/2022.08.08_develop_branch_Generic_System_Third_Party_cmod_thirdpartyownership.json"; std::string file_outputs = SSCDIR; @@ -94,7 +94,7 @@ TEST_F(CmodThirdPartyOwnershipTest, Generic) { } -TEST_F(CmodThirdPartyOwnershipTest, GenericBattery) { +TEST_F(CmodThirdPartyOwnershipTest, CustomGenerationBattery) { std::string file_inputs = SSCDIR; file_inputs += "/test/input_json/FinancialModels/thirdpartyownership/2022.08.08_develop_branch_Generic_Battery_Third_Party_cmod_thirdpartyownership.json"; std::string file_outputs = SSCDIR; From 81a2c044416ae2ee449ac79b1e18e7257f37ecad Mon Sep 17 00:00:00 2001 From: Matt Prilliman <54449384+mjprilliman@users.noreply.github.com> Date: Wed, 9 Oct 2024 18:21:52 -0500 Subject: [PATCH 5/8] Delete duplicate test files --- ssc/cmod_custom_generation.cpp | 2 +- test/ssc_test/cmod_generic_test.cpp | 139 ---------------------------- test/ssc_test/cmod_generic_test.h | 86 ----------------- 3 files changed, 1 insertion(+), 226 deletions(-) delete mode 100644 test/ssc_test/cmod_generic_test.cpp delete mode 100644 test/ssc_test/cmod_generic_test.h diff --git a/ssc/cmod_custom_generation.cpp b/ssc/cmod_custom_generation.cpp index 3e08747e9..f4615e708 100644 --- a/ssc/cmod_custom_generation.cpp +++ b/ssc/cmod_custom_generation.cpp @@ -256,5 +256,5 @@ class cm_custom_generation : public compute_module } // exec }; -DEFINE_MODULE_ENTRY( custom_generation, "Custom Generation Profile", 1 ); +DEFINE_MODULE_ENTRY( custom_generation, "Custom Generation Profile (formerly Generic System)", 1 ); diff --git a/test/ssc_test/cmod_generic_test.cpp b/test/ssc_test/cmod_generic_test.cpp deleted file mode 100644 index 4fd2272ff..000000000 --- a/test/ssc_test/cmod_generic_test.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* -BSD 3-Clause License - -Copyright (c) Alliance for Sustainable Energy, LLC. See also https://github.com/NREL/ssc/blob/develop/LICENSE -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include - -#include "cmod_custom_generation_test.h" - -/// Test Custom Generation Profile with Battery for SingleOwner PPA -TEST_F(CMCustomGeneration, SingleOwnerWithBattery_cmod_custom_generation) { - - custom_generation_singleowner_battery_60min(data); - - // Test different dispatch strategies - std::vector dispatch_options{ 0,2,3 }; - - // Run with hourly data - for (size_t i = 0; i < dispatch_options.size(); i++) { - ssc_data_set_number(data, "batt_dispatch_choice", (ssc_number_t)dispatch_options[i]); - EXPECT_FALSE(run_module(data, "custom_generation")); - EXPECT_FALSE(run_module(data, "battery")); - EXPECT_FALSE(run_module(data, "singleowner")); - } - - // Run with subhourly data - set_array(data, "energy_output_array", customgenerationtest::gen_path_30min, 8760 * 2); - set_array(data, "batt_custom_dispatch", customgenerationtest::batt_dispatch_path_30min, 8760 * 2); - set_array(data, "batt_room_temperature_celsius", customgenerationtest::temperature_path_30min, 8760 * 2); - for (size_t i = 0; i < dispatch_options.size(); i++) { - ssc_data_set_number(data, "batt_dispatch_choice", (ssc_number_t)dispatch_options[i]); - EXPECT_FALSE(run_module(data, "custom_generation")); - EXPECT_FALSE(run_module(data, "battery")); - EXPECT_FALSE(run_module(data, "singleowner")); - } - - // Test with incorrect combo of data sizes - ssc_data_set_number(data, "batt_dispatch_choice", 3); - set_array(data, "batt_custom_dispatch", customgenerationtest::batt_dispatch_path_30min, 8760*2); // 8760 or 8760 * 3 fails with execution error on Linux and windows - EXPECT_FALSE(run_module(data, "custom_generation")); - EXPECT_FALSE(run_module(data, "battery")); -} - -/// Test CustomGeneratoin System with Battery for various timesteps -TEST_F(CMCustomGeneration, CommercialWithBattery_cmod_custom_generation) { - - custom_generation_commerical_battery_60min(data); - - // Test different dispatch strategies - std::vector dispatch_options{ 0,2,3 }; - - // Run with hourly data, with and without lifetime - for (size_t l = 0; l < 2; l++) { - ssc_data_set_number(data, "system_use_lifetime_output", l); - for (size_t i = 0; i < dispatch_options.size(); i++) { - ssc_data_set_number(data, "batt_dispatch_choice", (ssc_number_t)dispatch_options[i]); - EXPECT_FALSE(run_module(data, "custom_generation")); - EXPECT_FALSE(run_module(data, "battery")); - EXPECT_FALSE(run_module(data, "utilityrate5")); - EXPECT_FALSE(run_module(data, "cashloan")); - } - } - - // Run with subhourly data - set_array(data, "energy_output_array", customgenerationtest::gen_path_30min, 8760 * 2); - set_array(data, "batt_custom_dispatch", customgenerationtest::batt_dispatch_path_30min, 8760 * 2); - set_array(data, "batt_room_temperature_celsius", customgenerationtest::temperature_path_30min, 8760 * 2); - set_array(data, "load", customgenerationtest::load_profile_path_30min, 8760 * 2); - - // With and without lifetime - for (size_t l = 0; l < 2; l++) { - ssc_data_set_number(data, "system_use_lifetime_output", l); - for (size_t i = 0; i < dispatch_options.size(); i++) { - ssc_data_set_number(data, "batt_dispatch_choice", (ssc_number_t)dispatch_options[i]); - EXPECT_FALSE(run_module(data, "custom_generation")); - EXPECT_FALSE(run_module(data, "battery")); - EXPECT_FALSE(run_module(data, "utilityrate5")); - EXPECT_FALSE(run_module(data, "cashloan")); - } - } - - // Test with hourly load, subhourly gen - ssc_data_set_number(data, "batt_dispatch_choice", 3); - set_array(data, "batt_custom_dispatch", customgenerationtest::batt_dispatch_path_30min, 8760 * 2); - set_array(data, "energy_output_array", customgenerationtest::gen_path_30min, 2*8760); - set_array(data, "batt_room_temperature_celsius", customgenerationtest::temperature_path_30min, 8760 * 2); - set_array(data, "load", customgenerationtest::load_profile_path_60min, 8760); - - for (size_t l = 0; l < 2; l++) { - ssc_data_set_number(data, "system_use_lifetime_output", l); - EXPECT_FALSE(run_module(data, "custom_generation")); - EXPECT_FALSE(run_module(data, "battery")); - } -} - -/* -Doesn't work to to outdated exeception handling methods in SSC which can not be -handled robustly in a cross-platform environment -https://docs.microsoft.com/en-us/cpp/cpp/errors-and-exception-handling-modern-cpp?view=vs-2017#c-exceptions-versus-windows-seh-exceptions -*/ -/* -TEST_F(CMCustomGeneration, CommericalWithBatteryWrongSizes) -{ - // Test with hourly gen, subhourly load, should fail everywhere - custom_generation_commerical_battery_60min(data); - set_array(data, "load", customgenerationtest::load_profile_path_30min, 2 * 8760); - - EXPECT_TRUE(run_module(data, "custom_generation_system")); - EXPECT_TRUE(run_module(data, "battery")); -} -*/ diff --git a/test/ssc_test/cmod_generic_test.h b/test/ssc_test/cmod_generic_test.h deleted file mode 100644 index cdc25d43f..000000000 --- a/test/ssc_test/cmod_generic_test.h +++ /dev/null @@ -1,86 +0,0 @@ -/* -BSD 3-Clause License - -Copyright (c) Alliance for Sustainable Energy, LLC. See also https://github.com/NREL/ssc/blob/develop/LICENSE -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - - -#ifndef _CMOD_CUSTOMGENERATION_TEST_H_ -#define _CMOD_CUSTOMGENERATION_TEST_H_ - -#include -#include - -#include "core.h" -#include "sscapi.h" - -#include "vartab.h" -#include "../ssc/common.h" -#include "../input_cases/code_generator_utilities.h" -#include "../input_cases/custom_generation_common_data.h" - -/** - * CMFuelCell tests the cmod_fuelcell using the SAM code generator to generate data - * Eventually a method can be written to write this data to a vartable so that lower-level methods of pvsamv1 can be tested - * For now, this uses the SSCAPI interfaces to run the compute module and compare results - */ -class CMCustomGeneration : public ::testing::Test { - -public: - - ssc_data_t data; - ssc_number_t calculated_value; - ssc_number_t * calculated_array; - double m_error_tolerance_hi = 1.0; - double m_error_tolerance_lo = 0.1; - - void SetUp() - { - data = ssc_data_create(); - } - void TearDown() { - if (data) { - ssc_data_free(data); - data = nullptr; - } - } - void SetCalculated(std::string name) - { - ssc_data_get_number(data, const_cast(name.c_str()), &calculated_value); - } - // apparently memory of the array is managed internally to the sscapi. - void SetCalculatedArray(std::string name) - { - int n; - calculated_array = ssc_data_get_array(data, const_cast(name.c_str()), &n); - } -}; - -#endif From 5531ee9ac84bdb6c86a668ea7ab0a43a68ffd2c1 Mon Sep 17 00:00:00 2001 From: Matt Prilliman <54449384+mjprilliman@users.noreply.github.com> Date: Thu, 10 Oct 2024 13:37:10 -0500 Subject: [PATCH 6/8] Update generic hybrid test files, table names --- ...on PVWatts Wind FuelCell Battery Hybrid_Single Owner.json} | 4 ++-- test/ssc_test/cmod_hybrid_test.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename test/input_json/hybrids/{Generic PVWatts Wind FuelCell Battery Hybrid_Single Owner.json => CustomGeneration PVWatts Wind FuelCell Battery Hybrid_Single Owner.json} (99%) diff --git a/test/input_json/hybrids/Generic PVWatts Wind FuelCell Battery Hybrid_Single Owner.json b/test/input_json/hybrids/CustomGeneration PVWatts Wind FuelCell Battery Hybrid_Single Owner.json similarity index 99% rename from test/input_json/hybrids/Generic PVWatts Wind FuelCell Battery Hybrid_Single Owner.json rename to test/input_json/hybrids/CustomGeneration PVWatts Wind FuelCell Battery Hybrid_Single Owner.json index 0303912d7..2ba39814e 100644 --- a/test/input_json/hybrids/Generic PVWatts Wind FuelCell Battery Hybrid_Single Owner.json +++ b/test/input_json/hybrids/CustomGeneration PVWatts Wind FuelCell Battery Hybrid_Single Owner.json @@ -1,6 +1,6 @@ { "input" : { - "compute_modules" : ["generic_system","pvwattsv8","windpower","fuelcell","battery","grid","utilityrate5","singleowner"], + "compute_modules" : ["custom_generation","pvwattsv8","windpower","fuelcell","battery","grid","utilityrate5","singleowner"], "windpower" : { "om_fixed_escal" : 0, "turb_specific_loss" : 0.81000000000000005, @@ -53,7 +53,7 @@ "om_production" : [ 0 ], "number table entries" : 50 }, - "generic_system" : { + "custom_generation" : { "adjust_en_timeindex" : 0, "om_capacity" : [ 40 ], "om_fuel_cost" : [ 10 ], diff --git a/test/ssc_test/cmod_hybrid_test.cpp b/test/ssc_test/cmod_hybrid_test.cpp index 85efc302d..4a8cf1773 100644 --- a/test/ssc_test/cmod_hybrid_test.cpp +++ b/test/ssc_test/cmod_hybrid_test.cpp @@ -155,7 +155,7 @@ TEST_F(CmodHybridTest, PVWattsv8WindBatteryHostDeveloper) { TEST_F(CmodHybridTest, CustomGenerationPVWattsWindFuelCellBatteryHybrid_SingleOwner) { char file_path[256]; - int nfc1 = sprintf(file_path, "%s/test/input_json/hybrids/Generic PVWatts Wind FuelCell Battery Hybrid_Single Owner.json", SSCDIR); + int nfc1 = sprintf(file_path, "%s/test/input_json/hybrids/CustomGeneration PVWatts Wind FuelCell Battery Hybrid_Single Owner.json", SSCDIR); std::ifstream file(file_path); std::ostringstream tmp; tmp << file.rdbuf(); From 8fc77160eb43999a5df5534a676d6ff3d1142270 Mon Sep 17 00:00:00 2001 From: Matt Prilliman <54449384+mjprilliman@users.noreply.github.com> Date: Mon, 28 Oct 2024 14:37:54 -0500 Subject: [PATCH 7/8] Add en_standalone_batt to custom generation battery test, remove duplicate generic data file from test --- .../custom_generation_common_data.h | 2 + test/input_cases/generic_common_data.h | 741 ------------------ 2 files changed, 2 insertions(+), 741 deletions(-) delete mode 100644 test/input_cases/generic_common_data.h diff --git a/test/input_cases/custom_generation_common_data.h b/test/input_cases/custom_generation_common_data.h index 2e84e744d..b25088cff 100644 --- a/test/input_cases/custom_generation_common_data.h +++ b/test/input_cases/custom_generation_common_data.h @@ -81,6 +81,7 @@ void custom_generation_singleowner_battery_60min(ssc_data_t &data) ssc_data_set_number( data, "en_batt", 1 ); + ssc_data_set_number(data, "en_standalone_batt", 0); ssc_data_set_number( data, "batt_replacement_option", 0 ); ssc_data_set_number( data, "batt_chem", 1 ); ssc_data_set_number( data, "batt_ac_or_dc", 1 ); @@ -448,6 +449,7 @@ void custom_generation_commerical_battery_60min(ssc_data_t &data) ssc_data_set_number(data, "adjust_constant", 0.0); ssc_data_set_number(data, "en_batt", 1); + ssc_data_set_number(data, "en_standalone_batt", 0); set_array(data, "load", customgenerationtest::load_profile_path_60min, 8760); ssc_data_set_number(data, "batt_replacement_option", 0); ssc_data_set_number(data, "batt_chem", 1); diff --git a/test/input_cases/generic_common_data.h b/test/input_cases/generic_common_data.h deleted file mode 100644 index 5fa8d4291..000000000 --- a/test/input_cases/generic_common_data.h +++ /dev/null @@ -1,741 +0,0 @@ -/* -BSD 3-Clause License - -Copyright (c) Alliance for Sustainable Energy, LLC. See also https://github.com/NREL/ssc/blob/develop/LICENSE -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#ifndef _CUSTOMGENERATION_COMMON_DATA_H_ -#define _CUSTOMGENERATION_COMMON_DATA_H_ - -#include -#include "code_generator_utilities.h" - -namespace customgenerationtest { - char load_profile_path_60min[256]; - char load_profile_path_30min[256]; - char gen_path_60min[256]; - char gen_path_30min[256]; - char batt_dispatch_path_30min[256]; - char batt_dispatch_path_60min[256]; - char dispatch_factors_unused[256]; - char sell_rate_unused[256]; - char temperature_path[256]; - char temperature_path_30min[256]; - - - int n1 = sprintf(load_profile_path_60min, "%s/test/input_cases/custom_generation_profile_data/load_60min.csv",SSCDIR); - int n2 = sprintf(load_profile_path_30min, "%s/test/input_cases/custom_generation_profile_data/load_30min.csv",SSCDIR); - int n3 = sprintf(gen_path_60min, "%s/test/input_cases/custom_generation_profile_data/energy_output_array_60min.csv",SSCDIR); - int n4 = sprintf(gen_path_30min, "%s/test/input_cases/custom_generation_profile_data/energy_output_array_30min.csv",SSCDIR); - int n5 = sprintf(batt_dispatch_path_30min, "%s/test/input_cases/custom_generation_profile_data/batt_custom_dispatch_30min.csv",SSCDIR); - int n6 = sprintf(batt_dispatch_path_60min, "%s/test/input_cases/custom_generation_profile_data/batt_custom_dispatch_60min.csv",SSCDIR); - int n7 = sprintf(dispatch_factors_unused, "%s/test/input_cases/custom_generation_profile_data/dispatch_factors_ts.csv",SSCDIR); - int n8 = sprintf(sell_rate_unused, "%s/test/input_cases/custom_generation_profile_data/ur_ts_sell_rate.csv",SSCDIR); - int n9 = sprintf(temperature_path, "%s/test/input_cases/battery_data/batt_room_temperature_celsius_60min.csv",SSCDIR); - int n10 = sprintf(temperature_path_30min, "%s/test/input_cases/battery_data/batt_room_temperature_celsius_30min.csv",SSCDIR); -} - - -void custom_generation_singleowner_battery_60min(ssc_data_t &data) -{ - ssc_data_set_number( data, "spec_mode", 1 ); - ssc_data_set_number( data, "derate", 0 ); - ssc_data_set_number( data, "system_capacity", 208842 ); - ssc_data_set_number( data, "user_capacity_factor", 43.599998474121094 ); - ssc_data_set_number( data, "heat_rate", 0 ); - ssc_data_set_number( data, "conv_eff", 0 ); - set_array( data, "energy_output_array", customgenerationtest::gen_path_60min, 8760); - ssc_data_set_number( data, "system_use_lifetime_output", 0 ); - ssc_data_set_number( data, "analysis_period", 25 ); - ssc_number_t p_generic_degradation[1] ={ 0 }; - ssc_data_set_array( data, "generic_degradation", p_generic_degradation, 1 ); - - ssc_data_set_number(data, "adjust_constant", 0.0); - - - ssc_data_set_number( data, "en_batt", 1 ); - ssc_data_set_number(data, "en_standalone_batt", 0); - ssc_data_set_number( data, "batt_replacement_option", 0 ); - ssc_data_set_number( data, "batt_chem", 1 ); - ssc_data_set_number( data, "batt_ac_or_dc", 1 ); - ssc_data_set_number( data, "batt_dc_dc_efficiency", 99 ); - ssc_data_set_number( data, "batt_dc_ac_efficiency", 96 ); - ssc_data_set_number( data, "batt_ac_dc_efficiency", 96 ); - ssc_data_set_number( data, "batt_meter_position", 1 ); - ssc_number_t p_batt_losses[1] ={ 0 }; - ssc_data_set_array( data, "batt_losses", p_batt_losses, 1 ); - ssc_number_t p_batt_losses_charging[12] ={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - ssc_data_set_array( data, "batt_losses_charging", p_batt_losses_charging, 12 ); - ssc_number_t p_batt_losses_discharging[12] ={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - ssc_data_set_array( data, "batt_losses_discharging", p_batt_losses_discharging, 12 ); - ssc_number_t p_batt_losses_idle[12] ={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - ssc_data_set_array( data, "batt_losses_idle", p_batt_losses_idle, 12 ); - ssc_data_set_number( data, "batt_loss_choice", 0 ); - ssc_data_set_number( data, "batt_current_choice", 1 ); - ssc_data_set_number( data, "batt_computed_strings", 1733583 ); - ssc_data_set_number( data, "batt_computed_series", 152 ); - ssc_data_set_number( data, "batt_computed_bank_capacity", 2000000 ); - ssc_data_set_number( data, "batt_current_charge_max", 1993620.375 ); - ssc_data_set_number( data, "batt_current_discharge_max", 1993620.375 ); - ssc_data_set_number( data, "batt_power_charge_max", 1000000 ); - ssc_data_set_number( data, "batt_power_discharge_max", 1000000 ); - ssc_data_set_number(data, "batt_inverter_efficiency_cutoff", 90); - ssc_data_set_number(data, "batt_power_charge_max_kwdc", 1000000); - ssc_data_set_number(data, "batt_power_discharge_max_kwdc", 1000000); - ssc_data_set_number(data, "batt_power_charge_max_kwac", 1000000); - ssc_data_set_number(data, "batt_power_discharge_max_kwac", 1000000); - ssc_data_set_number( data, "batt_voltage_choice", 0 ); - ssc_data_set_number( data, "batt_Vfull", 3.5999999046325684 ); - ssc_data_set_number( data, "batt_Vexp", 3.4000000953674316 ); - ssc_data_set_number( data, "batt_Vnom", 3.2999999523162842 ); - ssc_data_set_number(data, "batt_Vcut", 0.66 * 3.5999999046325684); - ssc_data_set_number( data, "batt_Vnom_default", 3.2999999523162842 ); - ssc_data_set_number( data, "batt_Qfull", 2.2999999523162842 ); - ssc_data_set_number( data, "batt_Qfull_flow", 3987240.75 ); - ssc_data_set_number( data, "batt_Qexp", 0.049910001456737518 ); - ssc_data_set_number( data, "batt_Qnom", 2.0446999073028564 ); - ssc_data_set_number( data, "batt_C_rate", 0.43000000715255737 ); - ssc_data_set_number( data, "batt_resistance", 0.0002 ); - ssc_number_t p_batt_voltage_matrix[2] ={ 0, 0 }; - ssc_data_set_matrix( data, "batt_voltage_matrix", p_batt_voltage_matrix, 1, 2 ); - ssc_data_set_number( data, "LeadAcid_q20_computed", 3987240.75 ); - ssc_data_set_number( data, "LeadAcid_q10_computed", 3708134 ); - ssc_data_set_number( data, "LeadAcid_qn_computed", 2392344.5 ); - ssc_data_set_number( data, "LeadAcid_tn", 1 ); - ssc_data_set_number( data, "batt_initial_SOC", 50 ); - ssc_data_set_number( data, "batt_minimum_SOC", 15 ); - ssc_data_set_number( data, "batt_maximum_SOC", 95 ); - ssc_data_set_number( data, "batt_minimum_modetime", 10 ); - ssc_data_set_number(data, "batt_life_model", 0); - ssc_number_t p_batt_lifetime_matrix[18] ={ 20, 0, 100, 20, 2500, 98, 20, 5000, 95, 80, 0, 100, 80, 500, 98, 80, 1000, 95 }; - ssc_data_set_matrix( data, "batt_lifetime_matrix", p_batt_lifetime_matrix, 6, 3 ); - ssc_data_set_number( data, "batt_calendar_choice", 1 ); - ssc_number_t p_batt_calendar_lifetime_matrix[6] ={ 0, 100, 3650, 80, 7300, 50 }; - ssc_data_set_matrix( data, "batt_calendar_lifetime_matrix", p_batt_calendar_lifetime_matrix, 3, 2 ); - ssc_data_set_number( data, "batt_calendar_q0", 1.0199999809265137 ); - ssc_data_set_number( data, "batt_calendar_a", 0.0026599999982863665 ); - ssc_data_set_number( data, "batt_calendar_b", -7280 ); - ssc_data_set_number( data, "batt_calendar_c", 930 ); - ssc_data_set_number( data, "batt_replacement_capacity", 0 ); - ssc_number_t p_batt_replacement_schedule[1] ={ 0 }; - ssc_data_set_array( data, "batt_replacement_schedule", p_batt_replacement_schedule, 1 ); - ssc_number_t p_replacement_cost[1] = { 600 }; - ssc_data_set_array(data, "om_batt_replacement_cost", p_replacement_cost, 1); - ssc_data_set_number( data, "batt_mass", 21489202 ); - ssc_data_set_number( data, "batt_surface_area", 2694 ); - ssc_data_set_number( data, "batt_Cp", 1004 ); - ssc_data_set_number( data, "batt_h_to_ambient", 20 ); - set_array(data, "batt_room_temperature_celsius", customgenerationtest::temperature_path, 8760); - ssc_number_t p_cap_vs_temp[8] ={ -10, 60, 0, 80, 25, 100, 40, 100 }; - ssc_data_set_matrix( data, "cap_vs_temp", p_cap_vs_temp, 4, 2 ); - ssc_number_t p_dispatch_manual_charge[6] ={ 1, 1, 1, 0, 0, 0 }; - ssc_data_set_array( data, "dispatch_manual_charge", p_dispatch_manual_charge, 6 ); - ssc_number_t p_dispatch_manual_discharge[6] ={ 0, 0, 1, 0, 0, 0 }; - ssc_data_set_array( data, "dispatch_manual_discharge", p_dispatch_manual_discharge, 6 ); - ssc_number_t p_dispatch_manual_gridcharge[6] ={ 0, 0, 0, 0, 0, 0 }; - ssc_data_set_array( data, "dispatch_manual_gridcharge", p_dispatch_manual_gridcharge, 6 ); - ssc_number_t p_dispatch_manual_percent_discharge[2] ={ 25, 0 }; - ssc_data_set_array( data, "dispatch_manual_percent_discharge", p_dispatch_manual_percent_discharge, 2 ); - ssc_number_t p_dispatch_manual_percent_gridcharge[1] ={ 0 }; - ssc_data_set_array( data, "dispatch_manual_percent_gridcharge", p_dispatch_manual_percent_gridcharge, 1 ); - ssc_number_t p_dispatch_manual_sched[288] ={ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1 }; - ssc_data_set_matrix( data, "dispatch_manual_sched", p_dispatch_manual_sched, 12, 24 ); - ssc_number_t p_dispatch_manual_sched_weekend[288] ={ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1 }; - ssc_data_set_matrix( data, "dispatch_manual_sched_weekend", p_dispatch_manual_sched_weekend, 12, 24 ); - set_array( data, "batt_custom_dispatch", customgenerationtest::batt_dispatch_path_60min, 8760); - ssc_data_set_number( data, "batt_dispatch_choice", 3 ); - ssc_number_t p_batt_pv_clipping_forecast[1] ={ 0 }; - ssc_data_set_array( data, "batt_pv_clipping_forecast", p_batt_pv_clipping_forecast, 1 ); - ssc_number_t p_batt_pv_dc_forecast[1] ={ 0 }; - ssc_data_set_array( data, "batt_pv_dc_forecast", p_batt_pv_dc_forecast, 1 ); - ssc_data_set_number( data, "batt_dispatch_auto_can_gridcharge", 0 ); - ssc_data_set_number( data, "batt_dispatch_auto_can_charge", 1 ); - ssc_data_set_number( data, "batt_dispatch_auto_can_clipcharge", 1 ); - ssc_data_set_number( data, "batt_auto_gridcharge_max_daily", 100 ); - ssc_data_set_number( data, "batt_look_ahead_hours", 18 ); - ssc_data_set_number( data, "batt_dispatch_update_frequency_hours", 1 ); - ssc_data_set_number( data, "batt_cycle_cost_choice", 0 ); - ssc_number_t p_batt_cycle_cost[1] = { 0.1 }; - ssc_data_set_array(data, "batt_cycle_cost", p_batt_cycle_cost, 1); - ssc_data_set_number( data, "en_electricity_rates", 0 ); - ssc_number_t p_ur_ec_sched_weekday[288] ={ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - ssc_data_set_matrix( data, "ur_ec_sched_weekday", p_ur_ec_sched_weekday, 12, 24 ); - ssc_number_t p_ur_ec_sched_weekend[288] ={ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - ssc_data_set_matrix( data, "ur_ec_sched_weekend", p_ur_ec_sched_weekend, 12, 24 ); - ssc_number_t p_ur_ec_tou_mat[30] ={ 1, 1, 9.9999996802856925e+37, 0, 0.094169996678829193, 0, 2, 1, 400, 0, 0.096869997680187225, 0, 2, 2, 800, 0, 0.13817000389099121, 0, 2, 3, 3000, 0, 0.16166999936103821, 0, 2, 4, 9.9999996802856925e+37, 0, 0.17257000505924225, 0 }; - ssc_data_set_matrix( data, "ur_ec_tou_mat", p_ur_ec_tou_mat, 5, 6 ); - ssc_data_set_number(data, "ur_en_ts_sell_rate", 0); - ssc_number_t p_ur_ts_buy_rate[1] = { 0 }; - ssc_data_set_array(data, "ur_ts_buy_rate", p_ur_ts_buy_rate, 1); - ssc_number_t p_ppa_price_input[1] = { 0 }; - ssc_data_set_array( data, "ppa_price_input", p_ppa_price_input, 1 ); - ssc_data_set_number(data, "cp_capacity_payment_esc", 0); - ssc_data_set_number(data, "cp_capacity_payment_type", 0); - ssc_data_set_number(data, "cp_system_nameplate", 0); - ssc_data_set_number(data, "cp_battery_nameplate", 0); - ssc_data_set_array(data, "cp_capacity_credit_percent", p_ppa_price_input, 1); - ssc_data_set_array( data, "cp_capacity_payment_amount", p_ppa_price_input, 1); - ssc_number_t p_dispatch_sched_weekday[288] ={ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - ssc_data_set_matrix( data, "dispatch_sched_weekday", p_dispatch_sched_weekday, 12, 24 ); - ssc_number_t p_dispatch_sched_weekend[288] ={ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - ssc_data_set_matrix( data, "dispatch_sched_weekend", p_dispatch_sched_weekend, 12, 24 ); - - ssc_number_t p_federal_tax_rate[1] ={ 21 }; - ssc_data_set_array( data, "federal_tax_rate", p_federal_tax_rate, 1 ); - ssc_number_t p_state_tax_rate[1] ={ 0 }; - ssc_data_set_array( data, "state_tax_rate", p_state_tax_rate, 1 ); - ssc_data_set_number( data, "property_tax_rate", 1 ); - ssc_data_set_number( data, "prop_tax_cost_assessed_percent", 100 ); - ssc_data_set_number( data, "prop_tax_assessed_decline", 0 ); - ssc_data_set_number( data, "real_discount_rate", 6.4000000953674316 ); - ssc_data_set_number( data, "inflation_rate", 2.5 ); - ssc_data_set_number( data, "insurance_rate", 1 ); - ssc_number_t p_om_fixed[1] ={ 0 }; - ssc_data_set_array( data, "om_fixed", p_om_fixed, 1 ); - ssc_data_set_number( data, "om_fixed_escal", 0 ); - ssc_number_t p_om_production[1] ={ 0 }; - ssc_data_set_array( data, "om_production", p_om_production, 1 ); - ssc_data_set_number( data, "om_production_escal", 0 ); - ssc_number_t p_om_capacity[1] ={ 50 }; - ssc_data_set_array( data, "om_capacity", p_om_capacity, 1 ); - ssc_data_set_number( data, "om_capacity_escal", 0 ); - ssc_number_t p_om_fuel_cost[1] ={ 0 }; - ssc_data_set_array( data, "om_fuel_cost", p_om_fuel_cost, 1 ); - ssc_data_set_number( data, "om_fuel_cost_escal", 0 ); - ssc_number_t itc_amount[1] = { 0 }; - ssc_number_t itc_fed_percent[1] = { 30 }; - ssc_number_t itc_sta_percent[1] = { 0 }; - ssc_number_t itc_amount_max[1] = { 1 }; - ssc_data_set_array(data, "itc_fed_amount", itc_amount, 1); - ssc_data_set_array(data, "itc_sta_amount", itc_amount, 1); - ssc_data_set_array(data, "itc_fed_percent", itc_fed_percent, 1); - ssc_data_set_array(data, "itc_sta_percent", itc_sta_percent, 1); - ssc_data_set_array(data, "itc_fed_percent_maxvalue", itc_amount_max, 1); - ssc_data_set_array(data, "itc_sta_percent_maxvalue", itc_amount_max, 1); - ssc_data_set_number( data, "itc_fed_amount_deprbas_fed", 1 ); - ssc_data_set_number( data, "itc_fed_amount_deprbas_sta", 1 ); - ssc_data_set_number( data, "itc_sta_amount_deprbas_fed", 0 ); - ssc_data_set_number( data, "itc_sta_amount_deprbas_sta", 0 ); - ssc_data_set_number( data, "itc_fed_percent_deprbas_fed", 1 ); - ssc_data_set_number( data, "itc_fed_percent_deprbas_sta", 1 ); - ssc_data_set_number( data, "itc_sta_percent_deprbas_fed", 0 ); - ssc_data_set_number( data, "itc_sta_percent_deprbas_sta", 0 ); - ssc_number_t p_ptc_fed_amount[1] ={ 0 }; - ssc_data_set_array( data, "ptc_fed_amount", p_ptc_fed_amount, 1 ); - ssc_data_set_number( data, "ptc_fed_term", 10 ); - ssc_data_set_number( data, "ptc_fed_escal", 0 ); - ssc_number_t p_ptc_sta_amount[1] ={ 0 }; - ssc_data_set_array( data, "ptc_sta_amount", p_ptc_sta_amount, 1 ); - ssc_data_set_number( data, "ptc_sta_term", 10 ); - ssc_data_set_number( data, "ptc_sta_escal", 0 ); - ssc_data_set_number( data, "ibi_fed_amount", 0 ); - ssc_data_set_number( data, "ibi_fed_amount_tax_fed", 1 ); - ssc_data_set_number( data, "ibi_fed_amount_tax_sta", 1 ); - ssc_data_set_number( data, "ibi_fed_amount_deprbas_fed", 0 ); - ssc_data_set_number( data, "ibi_fed_amount_deprbas_sta", 0 ); - ssc_data_set_number( data, "ibi_sta_amount", 0 ); - ssc_data_set_number( data, "ibi_sta_amount_tax_fed", 1 ); - ssc_data_set_number( data, "ibi_sta_amount_tax_sta", 1 ); - ssc_data_set_number( data, "ibi_sta_amount_deprbas_fed", 0 ); - ssc_data_set_number( data, "ibi_sta_amount_deprbas_sta", 0 ); - ssc_data_set_number( data, "ibi_uti_amount", 0 ); - ssc_data_set_number( data, "ibi_uti_amount_tax_fed", 1 ); - ssc_data_set_number( data, "ibi_uti_amount_tax_sta", 1 ); - ssc_data_set_number( data, "ibi_uti_amount_deprbas_fed", 0 ); - ssc_data_set_number( data, "ibi_uti_amount_deprbas_sta", 0 ); - ssc_data_set_number( data, "ibi_oth_amount", 0 ); - ssc_data_set_number( data, "ibi_oth_amount_tax_fed", 1 ); - ssc_data_set_number( data, "ibi_oth_amount_tax_sta", 1 ); - ssc_data_set_number( data, "ibi_oth_amount_deprbas_fed", 0 ); - ssc_data_set_number( data, "ibi_oth_amount_deprbas_sta", 0 ); - ssc_data_set_number( data, "ibi_fed_percent", 0 ); - ssc_data_set_number( data, "ibi_fed_percent_maxvalue", 0 ); - ssc_data_set_number( data, "ibi_fed_percent_tax_fed", 1 ); - ssc_data_set_number( data, "ibi_fed_percent_tax_sta", 1 ); - ssc_data_set_number( data, "ibi_fed_percent_deprbas_fed", 0 ); - ssc_data_set_number( data, "ibi_fed_percent_deprbas_sta", 0 ); - ssc_data_set_number( data, "ibi_sta_percent", 0 ); - ssc_data_set_number( data, "ibi_sta_percent_maxvalue", 0 ); - ssc_data_set_number( data, "ibi_sta_percent_tax_fed", 1 ); - ssc_data_set_number( data, "ibi_sta_percent_tax_sta", 1 ); - ssc_data_set_number( data, "ibi_sta_percent_deprbas_fed", 0 ); - ssc_data_set_number( data, "ibi_sta_percent_deprbas_sta", 0 ); - ssc_data_set_number( data, "ibi_uti_percent", 0 ); - ssc_data_set_number( data, "ibi_uti_percent_maxvalue", 0 ); - ssc_data_set_number( data, "ibi_uti_percent_tax_fed", 1 ); - ssc_data_set_number( data, "ibi_uti_percent_tax_sta", 1 ); - ssc_data_set_number( data, "ibi_uti_percent_deprbas_fed", 0 ); - ssc_data_set_number( data, "ibi_uti_percent_deprbas_sta", 0 ); - ssc_data_set_number( data, "ibi_oth_percent", 0 ); - ssc_data_set_number( data, "ibi_oth_percent_maxvalue", 0 ); - ssc_data_set_number( data, "ibi_oth_percent_tax_fed", 1 ); - ssc_data_set_number( data, "ibi_oth_percent_tax_sta", 1 ); - ssc_data_set_number( data, "ibi_oth_percent_deprbas_fed", 0 ); - ssc_data_set_number( data, "ibi_oth_percent_deprbas_sta", 0 ); - ssc_data_set_number( data, "cbi_fed_amount", 0 ); - ssc_data_set_number( data, "cbi_fed_maxvalue", 0 ); - ssc_data_set_number( data, "cbi_fed_tax_fed", 1 ); - ssc_data_set_number( data, "cbi_fed_tax_sta", 1 ); - ssc_data_set_number( data, "cbi_fed_deprbas_fed", 0 ); - ssc_data_set_number( data, "cbi_fed_deprbas_sta", 0 ); - ssc_data_set_number( data, "cbi_sta_amount", 0 ); - ssc_data_set_number( data, "cbi_sta_maxvalue", 0 ); - ssc_data_set_number( data, "cbi_sta_tax_fed", 1 ); - ssc_data_set_number( data, "cbi_sta_tax_sta", 1 ); - ssc_data_set_number( data, "cbi_sta_deprbas_fed", 0 ); - ssc_data_set_number( data, "cbi_sta_deprbas_sta", 0 ); - ssc_data_set_number( data, "cbi_uti_amount", 0 ); - ssc_data_set_number( data, "cbi_uti_maxvalue", 0 ); - ssc_data_set_number( data, "cbi_uti_tax_fed", 1 ); - ssc_data_set_number( data, "cbi_uti_tax_sta", 1 ); - ssc_data_set_number( data, "cbi_uti_deprbas_fed", 0 ); - ssc_data_set_number( data, "cbi_uti_deprbas_sta", 0 ); - ssc_data_set_number( data, "cbi_oth_amount", 0 ); - ssc_data_set_number( data, "cbi_oth_maxvalue", 0 ); - ssc_data_set_number( data, "cbi_oth_tax_fed", 1 ); - ssc_data_set_number( data, "cbi_oth_tax_sta", 1 ); - ssc_data_set_number( data, "cbi_oth_deprbas_fed", 0 ); - ssc_data_set_number( data, "cbi_oth_deprbas_sta", 0 ); - ssc_number_t p_pbi_fed_amount[1] ={ 0 }; - ssc_data_set_array( data, "pbi_fed_amount", p_pbi_fed_amount, 1 ); - ssc_data_set_number( data, "pbi_fed_term", 0 ); - ssc_data_set_number( data, "pbi_fed_escal", 0 ); - ssc_data_set_number( data, "pbi_fed_tax_fed", 1 ); - ssc_data_set_number( data, "pbi_fed_tax_sta", 1 ); - ssc_number_t p_pbi_sta_amount[1] ={ 0 }; - ssc_data_set_array( data, "pbi_sta_amount", p_pbi_sta_amount, 1 ); - ssc_data_set_number( data, "pbi_sta_term", 0 ); - ssc_data_set_number( data, "pbi_sta_escal", 0 ); - ssc_data_set_number( data, "pbi_sta_tax_fed", 1 ); - ssc_data_set_number( data, "pbi_sta_tax_sta", 1 ); - ssc_number_t p_pbi_uti_amount[1] ={ 0 }; - ssc_data_set_array( data, "pbi_uti_amount", p_pbi_uti_amount, 1 ); - ssc_data_set_number( data, "pbi_uti_term", 0 ); - ssc_data_set_number( data, "pbi_uti_escal", 0 ); - ssc_data_set_number( data, "pbi_uti_tax_fed", 1 ); - ssc_data_set_number( data, "pbi_uti_tax_sta", 1 ); - ssc_number_t p_pbi_oth_amount[1] ={ 0 }; - ssc_data_set_array( data, "pbi_oth_amount", p_pbi_oth_amount, 1 ); - ssc_data_set_number( data, "pbi_oth_term", 0 ); - ssc_data_set_number( data, "pbi_oth_escal", 0 ); - ssc_data_set_number( data, "pbi_oth_tax_fed", 1 ); - ssc_data_set_number( data, "pbi_oth_tax_sta", 1 ); - ssc_number_t p_degradation[1] ={ 0 }; - ssc_data_set_array( data, "degradation", p_degradation, 1 ); - ssc_data_set_number( data, "loan_moratorium", 0 ); - ssc_data_set_number( data, "system_use_recapitalization", 0 ); - ssc_data_set_number( data, "ppa_multiplier_model", 0 ); - set_array( data, "dispatch_factors_ts", customgenerationtest::dispatch_factors_unused, 8147); - ssc_number_t p_dispatch_tod_factors[9] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - ssc_data_set_array(data, "dispatch_tod_factors", p_dispatch_tod_factors, 9); - ssc_data_set_number( data, "total_installed_cost", 1554456064 ); - ssc_data_set_number( data, "reserves_interest", 1.75 ); - ssc_data_set_number( data, "equip1_reserve_cost", 0 ); - ssc_data_set_number( data, "equip1_reserve_freq", 0 ); - ssc_data_set_number( data, "equip2_reserve_cost", 0 ); - ssc_data_set_number( data, "equip2_reserve_freq", 0 ); - ssc_data_set_number( data, "equip3_reserve_cost", 0 ); - ssc_data_set_number( data, "equip3_reserve_freq", 0 ); - ssc_data_set_number( data, "equip_reserve_depr_sta", 0 ); - ssc_data_set_number( data, "equip_reserve_depr_fed", 0 ); - ssc_data_set_number( data, "salvage_percentage", 0 ); - ssc_data_set_number( data, "ppa_soln_mode", 1 ); - ssc_data_set_number( data, "ppa_escalation", 1 ); - ssc_data_set_number( data, "construction_financing_cost", 0 ); - ssc_data_set_number( data, "term_tenor", 0 ); - ssc_data_set_number( data, "term_int_rate", 0 ); - ssc_data_set_number( data, "dscr", 0 ); - ssc_data_set_number( data, "dscr_reserve_months", 0 ); - ssc_data_set_number( data, "debt_percent", 50 ); - ssc_data_set_number( data, "debt_option", 1 ); - ssc_data_set_number( data, "payment_option", 0 ); - ssc_data_set_number( data, "cost_debt_closing", 0 ); - ssc_data_set_number( data, "cost_debt_fee", 0 ); - ssc_data_set_number( data, "months_working_reserve", 6 ); - ssc_data_set_number( data, "months_receivables_reserve", 0 ); - ssc_data_set_number( data, "cost_other_financing", 0 ); - ssc_data_set_number( data, "flip_target_percent", 10 ); - ssc_data_set_number( data, "flip_target_year", 10 ); - ssc_data_set_number( data, "depr_alloc_macrs_5_percent", 100 ); - ssc_data_set_number( data, "depr_alloc_macrs_15_percent", 0 ); - ssc_data_set_number( data, "depr_alloc_sl_5_percent", 0 ); - ssc_data_set_number( data, "depr_alloc_sl_15_percent", 0 ); - ssc_data_set_number( data, "depr_alloc_sl_20_percent", 0 ); - ssc_data_set_number( data, "depr_alloc_sl_39_percent", 0 ); - ssc_data_set_number( data, "depr_alloc_custom_percent", 0 ); - ssc_number_t p_depr_custom_schedule[1] ={ 0 }; - ssc_data_set_array( data, "depr_custom_schedule", p_depr_custom_schedule, 1 ); - ssc_data_set_number( data, "depr_bonus_sta", 0 ); - ssc_data_set_number( data, "depr_bonus_sta_macrs_5", 0 ); - ssc_data_set_number( data, "depr_bonus_sta_macrs_15", 0 ); - ssc_data_set_number( data, "depr_bonus_sta_sl_5", 0 ); - ssc_data_set_number( data, "depr_bonus_sta_sl_15", 0 ); - ssc_data_set_number( data, "depr_bonus_sta_sl_20", 0 ); - ssc_data_set_number( data, "depr_bonus_sta_sl_39", 0 ); - ssc_data_set_number( data, "depr_bonus_sta_custom", 0 ); - ssc_data_set_number( data, "depr_bonus_fed", 0 ); - ssc_data_set_number( data, "depr_bonus_fed_macrs_5", 1 ); - ssc_data_set_number( data, "depr_bonus_fed_macrs_15", 0 ); - ssc_data_set_number( data, "depr_bonus_fed_sl_5", 0 ); - ssc_data_set_number( data, "depr_bonus_fed_sl_15", 0 ); - ssc_data_set_number( data, "depr_bonus_fed_sl_20", 0 ); - ssc_data_set_number( data, "depr_bonus_fed_sl_39", 0 ); - ssc_data_set_number( data, "depr_bonus_fed_custom", 0 ); - ssc_data_set_number( data, "depr_itc_sta_macrs_5", 0 ); - ssc_data_set_number( data, "depr_itc_sta_macrs_15", 0 ); - ssc_data_set_number( data, "depr_itc_sta_sl_5", 0 ); - ssc_data_set_number( data, "depr_itc_sta_sl_15", 0 ); - ssc_data_set_number( data, "depr_itc_sta_sl_20", 0 ); - ssc_data_set_number( data, "depr_itc_sta_sl_39", 0 ); - ssc_data_set_number( data, "depr_itc_sta_custom", 0 ); - ssc_data_set_number( data, "depr_itc_fed_macrs_5", 0 ); - ssc_data_set_number( data, "depr_itc_fed_macrs_15", 0 ); - ssc_data_set_number( data, "depr_itc_fed_sl_5", 0 ); - ssc_data_set_number( data, "depr_itc_fed_sl_15", 0 ); - ssc_data_set_number( data, "depr_itc_fed_sl_20", 0 ); - ssc_data_set_number( data, "depr_itc_fed_sl_39", 0 ); - ssc_data_set_number( data, "depr_itc_fed_custom", 0 ); - ssc_data_set_number( data, "pbi_fed_for_ds", 0 ); - ssc_data_set_number( data, "pbi_sta_for_ds", 0 ); - ssc_data_set_number( data, "pbi_uti_for_ds", 0 ); - ssc_data_set_number( data, "pbi_oth_for_ds", 0 ); - ssc_data_set_number( data, "depr_stabas_method", 1 ); - ssc_data_set_number( data, "depr_fedbas_method", 1 ); - ssc_data_set_number( data, "battery_per_kWh", 300 ); - ssc_data_set_number( data, "batt_replacement_cost_escal", 0 ); -} - -void custom_generation_commerical_battery_60min(ssc_data_t &data) -{ - ssc_data_set_number(data, "spec_mode", 1); - ssc_data_set_number(data, "derate", 4); - ssc_data_set_number(data, "system_capacity", 1.7090300321578979); - ssc_data_set_number(data, "user_capacity_factor", 43.599998474121094); - ssc_data_set_number(data, "heat_rate", 10); - ssc_data_set_number(data, "conv_eff", 34.118049621582031); - set_array(data, "energy_output_array", customgenerationtest::gen_path_60min, 8760); - ssc_data_set_number(data, "system_use_lifetime_output", 0); - ssc_data_set_number(data, "analysis_period", 25); - ssc_number_t p_generic_degradation[1] = { 0 }; - ssc_data_set_array(data, "generic_degradation", p_generic_degradation, 1); - - ssc_data_set_number(data, "adjust_constant", 0.0); - - ssc_data_set_number(data, "en_batt", 1); - ssc_data_set_number(data, "en_standalone_batt", 0); - set_array(data, "load", customgenerationtest::load_profile_path_60min, 8760); - ssc_data_set_number(data, "batt_replacement_option", 0); - ssc_data_set_number(data, "batt_chem", 1); - ssc_data_set_number(data, "batt_ac_or_dc", 1); - ssc_data_set_number(data, "batt_dc_dc_efficiency", 98); - ssc_data_set_number(data, "batt_dc_ac_efficiency", 96); - ssc_data_set_number(data, "batt_ac_dc_efficiency", 96); - ssc_data_set_number(data, "batt_meter_position", 0); - ssc_number_t p_batt_losses[1] = { 0 }; - ssc_data_set_array(data, "batt_losses", p_batt_losses, 1); - ssc_number_t p_batt_losses_charging[1] = { 0 }; - ssc_data_set_array(data, "batt_losses_charging", p_batt_losses_charging, 1); - ssc_number_t p_batt_losses_discharging[1] = { 0 }; - ssc_data_set_array(data, "batt_losses_discharging", p_batt_losses_discharging, 1); - ssc_number_t p_batt_losses_idle[1] = { 0 }; - ssc_data_set_array(data, "batt_losses_idle", p_batt_losses_idle, 1); - ssc_data_set_number(data, "batt_loss_choice", 0); - ssc_data_set_number(data, "batt_current_choice", 1); - ssc_data_set_number(data, "batt_computed_strings", 89); - ssc_data_set_number(data, "batt_computed_series", 139); - ssc_data_set_number(data, "batt_computed_bank_capacity", 100.20510101318359); - ssc_data_set_number(data, "batt_current_charge_max", 100.125); - ssc_data_set_number(data, "batt_current_discharge_max", 100.125); - ssc_data_set_number(data, "batt_inverter_efficiency_cutoff", 90); - ssc_data_set_number(data, "batt_power_charge_max_kwdc", 50.10255050659179); - ssc_data_set_number(data, "batt_power_discharge_max_kwdc", 50.10255050659179); - ssc_data_set_number(data, "batt_power_charge_max_kwac", 50.10255050659179); - ssc_data_set_number(data, "batt_power_discharge_max_kwac", 50.10255050659179); - ssc_data_set_number(data, "batt_voltage_choice", 0); - ssc_data_set_number(data, "batt_Vfull", 4.0999999046325684); - ssc_data_set_number(data, "batt_Vexp", 4.0500001907348633); - ssc_data_set_number(data, "batt_Vnom", 3.4000000953674316); - ssc_data_set_number(data, "batt_Vcut", 0.66 * 4.0999999046325684); - ssc_data_set_number(data, "batt_Vnom_default", 3.5999999046325684); - ssc_data_set_number(data, "batt_Qfull", 2.25); - ssc_data_set_number(data, "batt_Qfull_flow", 200.25); - ssc_data_set_number(data, "batt_Qexp", 0.040049999952316284); - ssc_data_set_number(data, "batt_Qnom", 2.0002501010894775); - ssc_data_set_number(data, "batt_C_rate", 0.20000000298023224); - ssc_data_set_number(data, "batt_resistance", 0.0002); - ssc_number_t p_batt_voltage_matrix[12] = { 0, 1.2000000476837158, 20, 1.1000000238418579, 40, 1.0499999523162842, 60, 1, 80, 0.94999998807907104, 100, 0.5 }; - ssc_data_set_matrix(data, "batt_voltage_matrix", p_batt_voltage_matrix, 6, 2); - ssc_data_set_number(data, "LeadAcid_q20_computed", 200.25); - ssc_data_set_number(data, "LeadAcid_q10_computed", 186.23249816894531); - ssc_data_set_number(data, "LeadAcid_qn_computed", 120.15000152587891); - ssc_data_set_number(data, "LeadAcid_tn", 1); - ssc_data_set_number(data, "batt_initial_SOC", 50); - ssc_data_set_number(data, "batt_minimum_SOC", 15); - ssc_data_set_number(data, "batt_maximum_SOC", 95); - ssc_data_set_number(data, "batt_minimum_modetime", 10); - ssc_data_set_number(data, "batt_life_model", 0); - ssc_number_t p_batt_lifetime_matrix[18] = { 20, 0, 100, 20, 5000, 80, 20, 10000, 60, 80, 0, 100, 80, 1000, 80, 80, 2000, 60 }; - ssc_data_set_matrix(data, "batt_lifetime_matrix", p_batt_lifetime_matrix, 6, 3); - ssc_data_set_number(data, "batt_calendar_choice", 0); - ssc_number_t p_batt_calendar_lifetime_matrix[6] = { 0, 100, 3650, 80, 7300, 50 }; - ssc_data_set_matrix(data, "batt_calendar_lifetime_matrix", p_batt_calendar_lifetime_matrix, 3, 2); - ssc_data_set_number(data, "batt_calendar_q0", 1.0199999809265137); - ssc_data_set_number(data, "batt_calendar_a", 0.0026599999982863665); - ssc_data_set_number(data, "batt_calendar_b", -7280); - ssc_data_set_number(data, "batt_calendar_c", 930); - ssc_data_set_number(data, "batt_replacement_capacity", 0); - ssc_number_t p_batt_replacement_schedule[1] = { 0 }; - ssc_data_set_array(data, "batt_replacement_schedule", p_batt_replacement_schedule, 1); - ssc_number_t p_replacement_cost[1] = { 600 }; - ssc_data_set_array(data, "om_batt_replacement_cost", p_replacement_cost, 1); - ssc_data_set_number(data, "batt_cycle_cost_choice", 0); - ssc_number_t p_batt_cycle_cost[1] = { 0.1 }; - ssc_data_set_array(data, "batt_cycle_cost", p_batt_cycle_cost, 1); - ssc_data_set_number(data, "batt_mass", 507.8046875); - ssc_data_set_number(data, "batt_surface_area", 2.05); - ssc_data_set_number(data, "batt_Cp", 1000); - ssc_data_set_number(data, "batt_h_to_ambient", 20); - set_array(data, "batt_room_temperature_celsius", customgenerationtest::temperature_path, 8760); - ssc_number_t p_cap_vs_temp[8] = { -15, 65, 0, 85, 25, 100, 40, 104 }; - ssc_data_set_matrix(data, "cap_vs_temp", p_cap_vs_temp, 4, 2); - ssc_number_t p_dispatch_manual_charge[6] = { 1, 1, 1, 0, 0, 0 }; - ssc_data_set_array(data, "dispatch_manual_charge", p_dispatch_manual_charge, 6); - ssc_number_t p_dispatch_manual_discharge[6] = { 0, 0, 1, 0, 0, 0 }; - ssc_data_set_array(data, "dispatch_manual_discharge", p_dispatch_manual_discharge, 6); - ssc_number_t p_dispatch_manual_gridcharge[6] = { 0, 1, 0, 0, 0, 0 }; - ssc_data_set_array(data, "dispatch_manual_gridcharge", p_dispatch_manual_gridcharge, 6); - ssc_number_t p_dispatch_manual_discharge_to_grid[6] = { 0, 0, 0, 0, 0, 0 }; - ssc_data_set_array(data, "dispatch_manual_btm_discharge_to_grid", p_dispatch_manual_discharge_to_grid, 6); - ssc_number_t p_dispatch_manual_percent_discharge[2] = { 25, 0 }; - ssc_data_set_array(data, "dispatch_manual_percent_discharge", p_dispatch_manual_percent_discharge, 2); - ssc_number_t p_dispatch_manual_percent_gridcharge[2] = { 100, 0 }; - ssc_data_set_array(data, "dispatch_manual_percent_gridcharge", p_dispatch_manual_percent_gridcharge, 2); - ssc_number_t p_dispatch_manual_sched[288] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1 }; - ssc_data_set_matrix(data, "dispatch_manual_sched", p_dispatch_manual_sched, 12, 24); - ssc_number_t p_dispatch_manual_sched_weekend[288] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 1, 1, 1, 1 }; - ssc_data_set_matrix(data, "dispatch_manual_sched_weekend", p_dispatch_manual_sched_weekend, 12, 24); - ssc_number_t p_batt_target_power[1] = { 15 }; - ssc_data_set_array(data, "batt_target_power", p_batt_target_power, 1); - ssc_number_t p_batt_target_power_monthly[1] = { 0 }; - ssc_data_set_array(data, "batt_target_power_monthly", p_batt_target_power_monthly, 1); - ssc_data_set_number(data, "batt_target_choice", 0); - set_array(data, "batt_custom_dispatch", customgenerationtest::batt_dispatch_path_60min, 8760); - ssc_data_set_number(data, "batt_dispatch_choice", 3); - ssc_data_set_number(data, "batt_dispatch_auto_can_gridcharge", 0); - ssc_data_set_number(data, "batt_dispatch_auto_can_charge", 1); - ssc_data_set_number(data, "batt_dispatch_charge_only_system_exceeds_load", 1); - ssc_data_set_number(data, "batt_dispatch_discharge_only_load_exceeds_system", 1); - ssc_number_t p_ur_ec_sched_weekday[288] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - ssc_data_set_matrix(data, "ur_ec_sched_weekday", p_ur_ec_sched_weekday, 12, 24); - ssc_number_t p_ur_ec_sched_weekend[288] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - ssc_data_set_matrix(data, "ur_ec_sched_weekend", p_ur_ec_sched_weekend, 12, 24); - ssc_number_t p_ur_ec_tou_mat[30] = { 1, 1, 9.9999996802856925e+37, 0, 0.094169996678829193, 0, 2, 1, 400, 0, 0.096869997680187225, 0, 2, 2, 800, 0, 0.13817000389099121, 0, 2, 3, 3000, 0, 0.16166999936103821, 0, 2, 4, 9.9999996802856925e+37, 0, 0.17257000505924225, 0 }; - ssc_data_set_matrix(data, "ur_ec_tou_mat", p_ur_ec_tou_mat, 5, 6); - - ssc_data_set_number(data, "inflation_rate", 2.5); - ssc_number_t p_degradation[1] = { 0 }; - ssc_data_set_array(data, "degradation", p_degradation, 1); - ssc_number_t p_load_escalation[1] = { 0 }; - ssc_data_set_array(data, "load_escalation", p_load_escalation, 1); - ssc_number_t p_rate_escalation[1] = { 0 }; - ssc_data_set_array(data, "rate_escalation", p_rate_escalation, 1); - ssc_data_set_number(data, "ur_metering_option", 2); - ssc_data_set_number(data, "ur_nm_yearend_sell_rate", 0.027890000492334366); - ssc_data_set_number(data, "ur_monthly_fixed_charge", 8.5500001907348633); - ssc_data_set_number(data, "ur_monthly_min_charge", 0); - ssc_data_set_number(data, "ur_annual_min_charge", 0); - ssc_data_set_number(data, "ur_en_ts_sell_rate", 0); - set_array(data, "ur_ts_sell_rate", customgenerationtest::sell_rate_unused, 8760); - ssc_data_set_number(data, "ur_dc_enable", 1); - ssc_number_t p_ur_dc_sched_weekday[288] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - ssc_data_set_matrix(data, "ur_dc_sched_weekday", p_ur_dc_sched_weekday, 12, 24); - ssc_number_t p_ur_dc_sched_weekend[288] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - ssc_data_set_matrix(data, "ur_dc_sched_weekend", p_ur_dc_sched_weekend, 12, 24); - ssc_number_t p_ur_dc_tou_mat[4] = { 1, 1, 0, 0 }; - ssc_data_set_matrix(data, "ur_dc_tou_mat", p_ur_dc_tou_mat, 1, 4); - ssc_number_t p_ur_dc_flat_mat[48] = { 0, 1, 0, 0, 1, 1, 0, 0, 2, 1, 0, 0, 3, 1, 0, 0, 4, 1, 0, 0, 5, 1, 0, 0, 6, 1, 0, 0, 7, 1, 0, 0, 8, 1, 0, 0, 9, 1, 0, 0, 10, 1, 0, 0, 11, 1, 0, 0 }; - ssc_data_set_matrix(data, "ur_dc_flat_mat", p_ur_dc_flat_mat, 12, 4); - - ssc_number_t p_federal_tax_rate[1] = { 21 }; - ssc_data_set_array(data, "federal_tax_rate", p_federal_tax_rate, 1); - ssc_number_t p_state_tax_rate[1] = { 7 }; - ssc_data_set_array(data, "state_tax_rate", p_state_tax_rate, 1); - ssc_data_set_number(data, "property_tax_rate", 0); - ssc_data_set_number(data, "prop_tax_cost_assessed_percent", 100); - ssc_data_set_number(data, "prop_tax_assessed_decline", 0); - ssc_data_set_number(data, "real_discount_rate", 6.4000000953674316); - ssc_data_set_number(data, "insurance_rate", 0.5); - ssc_data_set_number(data, "loan_term", 25); - ssc_data_set_number(data, "loan_rate", 7.5); - ssc_data_set_number(data, "debt_fraction", 100); - ssc_number_t p_om_fixed[1] = { 0 }; - ssc_data_set_array(data, "om_fixed", p_om_fixed, 1); - ssc_data_set_number(data, "om_fixed_escal", 0); - ssc_number_t p_om_production[1] = { 0 }; - ssc_data_set_array(data, "om_production", p_om_production, 1); - ssc_data_set_number(data, "om_production_escal", 0); - ssc_number_t p_om_capacity[1] = { 25 }; - ssc_data_set_array(data, "om_capacity", p_om_capacity, 1); - ssc_data_set_number(data, "om_capacity_escal", 0); - ssc_number_t p_om_fuel_cost[1] = { 8 }; - ssc_data_set_array(data, "om_fuel_cost", p_om_fuel_cost, 1); - ssc_data_set_number(data, "om_fuel_cost_escal", 0); - ssc_data_set_number(data, "depr_fed_type", 1); - ssc_data_set_number(data, "depr_fed_sl_years", 7); - ssc_number_t p_depr_fed_custom[1] = { 0 }; - ssc_data_set_array(data, "depr_fed_custom", p_depr_fed_custom, 1); - ssc_data_set_number(data, "depr_sta_type", 1); - ssc_data_set_number(data, "depr_sta_sl_years", 7); - ssc_number_t p_depr_sta_custom[1] = { 0 }; - ssc_data_set_array(data, "depr_sta_custom", p_depr_sta_custom, 1); - ssc_number_t itc_amount[1] = { 0 }; - ssc_number_t itc_fed_percent[1] = { 0 }; - ssc_number_t itc_sta_percent[1] = { 0 }; - ssc_number_t itc_amount_max[1] = { 1e+38 }; - ssc_data_set_array(data, "itc_fed_amount", itc_amount, 1); - ssc_data_set_array(data, "itc_sta_amount", itc_amount, 1); - ssc_data_set_array(data, "itc_fed_percent", itc_fed_percent, 1); - ssc_data_set_array(data, "itc_sta_percent", itc_sta_percent, 1); - ssc_data_set_array(data, "itc_fed_percent_maxvalue", itc_amount_max, 1); - ssc_data_set_array(data, "itc_sta_percent_maxvalue", itc_amount_max, 1); - ssc_data_set_number(data, "itc_fed_amount_deprbas_fed", 1); - ssc_data_set_number(data, "itc_fed_amount_deprbas_sta", 1); - ssc_data_set_number(data, "itc_sta_amount_deprbas_fed", 0); - ssc_data_set_number(data, "itc_sta_amount_deprbas_sta", 0); - ssc_data_set_number(data, "itc_fed_percent_deprbas_fed", 1); - ssc_data_set_number(data, "itc_fed_percent_deprbas_sta", 1); - ssc_data_set_number(data, "itc_sta_percent_deprbas_fed", 0); - ssc_data_set_number(data, "itc_sta_percent_deprbas_sta", 0); - ssc_number_t p_ptc_fed_amount[1] = { 0 }; - ssc_data_set_array(data, "ptc_fed_amount", p_ptc_fed_amount, 1); - ssc_data_set_number(data, "ptc_fed_term", 10); - ssc_data_set_number(data, "ptc_fed_escal", 0); - ssc_number_t p_ptc_sta_amount[1] = { 0 }; - ssc_data_set_array(data, "ptc_sta_amount", p_ptc_sta_amount, 1); - ssc_data_set_number(data, "ptc_sta_term", 10); - ssc_data_set_number(data, "ptc_sta_escal", 0); - ssc_data_set_number(data, "ibi_fed_amount", 0); - ssc_data_set_number(data, "ibi_fed_amount_tax_fed", 1); - ssc_data_set_number(data, "ibi_fed_amount_tax_sta", 1); - ssc_data_set_number(data, "ibi_fed_amount_deprbas_fed", 0); - ssc_data_set_number(data, "ibi_fed_amount_deprbas_sta", 0); - ssc_data_set_number(data, "ibi_sta_amount", 0); - ssc_data_set_number(data, "ibi_sta_amount_tax_fed", 1); - ssc_data_set_number(data, "ibi_sta_amount_tax_sta", 1); - ssc_data_set_number(data, "ibi_sta_amount_deprbas_fed", 0); - ssc_data_set_number(data, "ibi_sta_amount_deprbas_sta", 0); - ssc_data_set_number(data, "ibi_uti_amount", 0); - ssc_data_set_number(data, "ibi_uti_amount_tax_fed", 1); - ssc_data_set_number(data, "ibi_uti_amount_tax_sta", 1); - ssc_data_set_number(data, "ibi_uti_amount_deprbas_fed", 0); - ssc_data_set_number(data, "ibi_uti_amount_deprbas_sta", 0); - ssc_data_set_number(data, "ibi_oth_amount", 0); - ssc_data_set_number(data, "ibi_oth_amount_tax_fed", 1); - ssc_data_set_number(data, "ibi_oth_amount_tax_sta", 1); - ssc_data_set_number(data, "ibi_oth_amount_deprbas_fed", 0); - ssc_data_set_number(data, "ibi_oth_amount_deprbas_sta", 0); - ssc_data_set_number(data, "ibi_fed_percent", 0); - ssc_data_set_number(data, "ibi_fed_percent_maxvalue", 9.9999996802856925e+37); - ssc_data_set_number(data, "ibi_fed_percent_tax_fed", 1); - ssc_data_set_number(data, "ibi_fed_percent_tax_sta", 1); - ssc_data_set_number(data, "ibi_fed_percent_deprbas_fed", 0); - ssc_data_set_number(data, "ibi_fed_percent_deprbas_sta", 0); - ssc_data_set_number(data, "ibi_sta_percent", 0); - ssc_data_set_number(data, "ibi_sta_percent_maxvalue", 9.9999996802856925e+37); - ssc_data_set_number(data, "ibi_sta_percent_tax_fed", 1); - ssc_data_set_number(data, "ibi_sta_percent_tax_sta", 1); - ssc_data_set_number(data, "ibi_sta_percent_deprbas_fed", 0); - ssc_data_set_number(data, "ibi_sta_percent_deprbas_sta", 0); - ssc_data_set_number(data, "ibi_uti_percent", 0); - ssc_data_set_number(data, "ibi_uti_percent_maxvalue", 9.9999996802856925e+37); - ssc_data_set_number(data, "ibi_uti_percent_tax_fed", 1); - ssc_data_set_number(data, "ibi_uti_percent_tax_sta", 1); - ssc_data_set_number(data, "ibi_uti_percent_deprbas_fed", 0); - ssc_data_set_number(data, "ibi_uti_percent_deprbas_sta", 0); - ssc_data_set_number(data, "ibi_oth_percent", 0); - ssc_data_set_number(data, "ibi_oth_percent_maxvalue", 9.9999996802856925e+37); - ssc_data_set_number(data, "ibi_oth_percent_tax_fed", 1); - ssc_data_set_number(data, "ibi_oth_percent_tax_sta", 1); - ssc_data_set_number(data, "ibi_oth_percent_deprbas_fed", 0); - ssc_data_set_number(data, "ibi_oth_percent_deprbas_sta", 0); - ssc_data_set_number(data, "cbi_fed_amount", 0); - ssc_data_set_number(data, "cbi_fed_maxvalue", 9.9999996802856925e+37); - ssc_data_set_number(data, "cbi_fed_tax_fed", 1); - ssc_data_set_number(data, "cbi_fed_tax_sta", 1); - ssc_data_set_number(data, "cbi_fed_deprbas_fed", 0); - ssc_data_set_number(data, "cbi_fed_deprbas_sta", 0); - ssc_data_set_number(data, "cbi_sta_amount", 0); - ssc_data_set_number(data, "cbi_sta_maxvalue", 9.9999996802856925e+37); - ssc_data_set_number(data, "cbi_sta_tax_fed", 1); - ssc_data_set_number(data, "cbi_sta_tax_sta", 1); - ssc_data_set_number(data, "cbi_sta_deprbas_fed", 0); - ssc_data_set_number(data, "cbi_sta_deprbas_sta", 0); - ssc_data_set_number(data, "cbi_uti_amount", 0); - ssc_data_set_number(data, "cbi_uti_maxvalue", 9.9999996802856925e+37); - ssc_data_set_number(data, "cbi_uti_tax_fed", 1); - ssc_data_set_number(data, "cbi_uti_tax_sta", 1); - ssc_data_set_number(data, "cbi_uti_deprbas_fed", 0); - ssc_data_set_number(data, "cbi_uti_deprbas_sta", 0); - ssc_data_set_number(data, "cbi_oth_amount", 0); - ssc_data_set_number(data, "cbi_oth_maxvalue", 9.9999996802856925e+37); - ssc_data_set_number(data, "cbi_oth_tax_fed", 1); - ssc_data_set_number(data, "cbi_oth_tax_sta", 1); - ssc_data_set_number(data, "cbi_oth_deprbas_fed", 0); - ssc_data_set_number(data, "cbi_oth_deprbas_sta", 0); - ssc_number_t p_pbi_fed_amount[1] = { 0 }; - ssc_data_set_array(data, "pbi_fed_amount", p_pbi_fed_amount, 1); - ssc_data_set_number(data, "pbi_fed_term", 0); - ssc_data_set_number(data, "pbi_fed_escal", 0); - ssc_data_set_number(data, "pbi_fed_tax_fed", 1); - ssc_data_set_number(data, "pbi_fed_tax_sta", 1); - ssc_number_t p_pbi_sta_amount[1] = { 0 }; - ssc_data_set_array(data, "pbi_sta_amount", p_pbi_sta_amount, 1); - ssc_data_set_number(data, "pbi_sta_term", 0); - ssc_data_set_number(data, "pbi_sta_escal", 0); - ssc_data_set_number(data, "pbi_sta_tax_fed", 1); - ssc_data_set_number(data, "pbi_sta_tax_sta", 1); - ssc_number_t p_pbi_uti_amount[1] = { 0 }; - ssc_data_set_array(data, "pbi_uti_amount", p_pbi_uti_amount, 1); - ssc_data_set_number(data, "pbi_uti_term", 0); - ssc_data_set_number(data, "pbi_uti_escal", 0); - ssc_data_set_number(data, "pbi_uti_tax_fed", 1); - ssc_data_set_number(data, "pbi_uti_tax_sta", 1); - ssc_number_t p_pbi_oth_amount[1] = { 0 }; - ssc_data_set_array(data, "pbi_oth_amount", p_pbi_oth_amount, 1); - ssc_data_set_number(data, "pbi_oth_term", 0); - ssc_data_set_number(data, "pbi_oth_escal", 0); - ssc_data_set_number(data, "pbi_oth_tax_fed", 1); - ssc_data_set_number(data, "pbi_oth_tax_sta", 1); - ssc_data_set_number(data, "battery_per_kWh", 300); - ssc_data_set_number(data, "batt_replacement_cost_escal", 0); - ssc_data_set_number(data, "total_installed_cost", 86827.921875); - ssc_data_set_number(data, "salvage_percentage", 0); -} -#endif From 6ab0b01d0a550d4b358bc271af593ffcfc3326ca Mon Sep 17 00:00:00 2001 From: Brian Mirletz Date: Thu, 31 Oct 2024 08:37:04 -0600 Subject: [PATCH 8/8] Sam 181 interconnection limits (#1224) * First draft discharging constraints based on interconnection limits for FOM automated and manual dispatch * New variable to control ability to charge from curtailed power independently from system power * Incorporate curtail charging into powerflow and manual dispatch. Functional for fom automated and manual dispatch. * Add to retail rates dispatch, consider curtailment limits FOM * Tests for interconnection limits * Change label to match new GUI label * Correct comment on interconnection limits * Update charging with efficiency numbers so energy more consistently makes it to the grid at the interconnection limit * Move curtail charging closer to clip charging to encourage it. Significant decrease in curtailed energy when the battery is not full * Add or statements such that battery always tries to charge from curtailed power --- shared/lib_battery_dispatch.cpp | 2 + shared/lib_battery_dispatch.h | 1 + shared/lib_battery_dispatch_automatic_btm.cpp | 38 +++++- shared/lib_battery_dispatch_automatic_btm.h | 1 + shared/lib_battery_dispatch_automatic_fom.cpp | 20 ++- shared/lib_battery_dispatch_automatic_fom.h | 2 + shared/lib_battery_dispatch_manual.cpp | 20 ++- shared/lib_battery_dispatch_manual.h | 3 + .../lib_battery_dispatch_pvsmoothing_fom.cpp | 4 +- shared/lib_battery_dispatch_pvsmoothing_fom.h | 1 + shared/lib_battery_powerflow.cpp | 24 +++- shared/lib_battery_powerflow.h | 3 +- ssc/cmod_battery.cpp | 16 ++- ssc/cmod_battery.h | 3 + ...ib_battery_dispatch_automatic_btm_test.cpp | 54 ++++---- ...ib_battery_dispatch_automatic_fom_test.cpp | 116 +++++++++++++++--- .../lib_battery_dispatch_manual_test.cpp | 89 +++++++++++--- test/shared_test/lib_battery_dispatch_test.h | 1 + 18 files changed, 314 insertions(+), 84 deletions(-) diff --git a/shared/lib_battery_dispatch.cpp b/shared/lib_battery_dispatch.cpp index f5327da41..a98e1c428 100644 --- a/shared/lib_battery_dispatch.cpp +++ b/shared/lib_battery_dispatch.cpp @@ -651,6 +651,7 @@ dispatch_automatic_t::dispatch_automatic_t( bool can_clip_charge, bool can_grid_charge, bool can_fuelcell_charge, + bool can_curtail_charge, std::vector battReplacementCostPerkWh, int battCycleCostChoice, std::vector battCycleCost, @@ -684,6 +685,7 @@ dispatch_automatic_t::dispatch_automatic_t( _safety_factor = 0.0; m_batteryPower->canClipCharge = can_clip_charge; + m_batteryPower->canCurtailCharge = can_curtail_charge; m_batteryPower->canSystemCharge = can_charge; m_batteryPower->canGridCharge = can_grid_charge; m_batteryPower->canFuelCellCharge = can_fuelcell_charge; diff --git a/shared/lib_battery_dispatch.h b/shared/lib_battery_dispatch.h index df49cd3bf..c1f701b2e 100644 --- a/shared/lib_battery_dispatch.h +++ b/shared/lib_battery_dispatch.h @@ -317,6 +317,7 @@ class dispatch_automatic_t : public dispatch_t bool can_clipcharge, bool can_grid_charge, bool can_fuelcell_charge, + bool can_curtail_charge, std::vector battReplacementCostPerkWh, int battCycleCostChoice, std::vector battCycleCost, diff --git a/shared/lib_battery_dispatch_automatic_btm.cpp b/shared/lib_battery_dispatch_automatic_btm.cpp index 4582dd83f..9ef100e67 100644 --- a/shared/lib_battery_dispatch_automatic_btm.cpp +++ b/shared/lib_battery_dispatch_automatic_btm.cpp @@ -61,6 +61,7 @@ dispatch_automatic_behind_the_meter_t::dispatch_automatic_behind_the_meter_t( bool can_clip_charge, bool can_grid_charge, bool can_fuelcell_charge, + bool can_curtail_charge, rate_data* util_rate, std::vector battReplacementCostPerkWh, int battCycleCostChoice, @@ -73,7 +74,8 @@ dispatch_automatic_behind_the_meter_t::dispatch_automatic_behind_the_meter_t( double SOC_min_outage, int load_forecast_mode ) : dispatch_automatic_t(Battery, dt_hour, SOC_min, SOC_max, current_choice, Ic_max, Id_max, Pc_max_kwdc, Pd_max_kwdc, Pc_max_kwac, Pd_max_kwac, - t_min, dispatch_mode, weather_forecast_mode, pv_dispatch, nyears, look_ahead_hours, dispatch_update_frequency_hours, can_charge, can_clip_charge, can_grid_charge, can_fuelcell_charge, + t_min, dispatch_mode, weather_forecast_mode, pv_dispatch, nyears, look_ahead_hours, dispatch_update_frequency_hours, + can_charge, can_clip_charge, can_grid_charge, can_fuelcell_charge, can_curtail_charge, battReplacementCostPerkWh, battCycleCostChoice, battCycleCost, battOMCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, behindTheMeterDischargeToGrid, SOC_min_outage) { @@ -401,10 +403,10 @@ double dispatch_automatic_behind_the_meter_t::compute_costs(size_t idx, size_t y year++; } for (size_t step = 0; step != _steps_per_hour && idx < _P_load_ac.size(); step++) - { + { double power = _P_load_ac[idx] - _P_pv_ac[idx]; - // One at a time so we can sort grid points by no-dispatch cost - std::vector forecast_power = { -power }; // Correct sign convention for cost forecast + // One at a time so we can sort grid points by no-dispatch cost; TODO: consider curtailment limits - would need to pass in a forecast of these... + std::vector forecast_power = { std::fmin(-1.0*power, m_batteryPower->powerInterconnectionLimit)}; // Correct sign convention for cost forecast double step_cost = noDispatchForecast->forecastCost(forecast_power, year, (hour_of_year + hour) % 8760, step); no_dispatch_cost += step_cost; @@ -707,6 +709,30 @@ void dispatch_automatic_behind_the_meter_t::plan_dispatch_for_cost(dispatch_plan } } + // Iterate over sorted grid to prioritize curtail charging + i = 0; + if (m_batteryPower->canCurtailCharge || m_batteryPower->canSystemCharge) { + while (i < _num_steps) { + // Don't plan to charge if we were already planning to discharge. 0 is no plan, negative is clipped energy + index = sorted_grid[i].Hour() * _steps_per_hour + sorted_grid[i].Step(); + if (plan.plannedDispatch[index] <= 0.0) + { + double requiredPower = 0.0; + if (sorted_grid[i].Grid() < 0) { + double powerLimit = std::fmin(m_batteryPower->powerInterconnectionLimit, m_batteryPower->powerCurtailmentLimit); + requiredPower = sorted_grid[i].Grid() + powerLimit; + requiredPower = std::fmin(0.0, requiredPower); + } + // Add to existing clipped energy + requiredPower += plan.plannedDispatch[index]; + // Clipped energy was already counted once, so subtract that off incase requiredPower + clipped hit a current restriction + requiredEnergy += (requiredPower - plan.plannedDispatch[index]) * _dt_hour; + plan.plannedDispatch[index] = requiredPower; + } + i++; + } + } + // Iterating over sorted grid std::stable_sort(sorted_grid.begin(), sorted_grid.end(), byLowestMarginalCost()); // Find m hours to get required energy - hope we got today's energy yesterday (for morning peaks). Apportion between hrs of lowest marginal cost @@ -765,9 +791,9 @@ void dispatch_automatic_behind_the_meter_t::plan_dispatch_for_cost(dispatch_plan // Clipped energy was already counted once, so subtract that off incase requiredPower + clipped hit a current restriction requiredEnergy += (requiredPower - plan.plannedDispatch[index]) * _dt_hour; - } - plan.plannedDispatch[index] = requiredPower; + plan.plannedDispatch[index] = requiredPower; + } } i++; diff --git a/shared/lib_battery_dispatch_automatic_btm.h b/shared/lib_battery_dispatch_automatic_btm.h index 2d963a18a..34d3bbd5b 100644 --- a/shared/lib_battery_dispatch_automatic_btm.h +++ b/shared/lib_battery_dispatch_automatic_btm.h @@ -86,6 +86,7 @@ class dispatch_automatic_behind_the_meter_t : public dispatch_automatic_t bool can_clipcharge, bool can_grid_charge, bool can_fuelcell_charge, + bool can_curtail_charge, rate_data* util_rate, std::vector battReplacementCostPerkWh, int battCycleCostChoice, diff --git a/shared/lib_battery_dispatch_automatic_fom.cpp b/shared/lib_battery_dispatch_automatic_fom.cpp index 66a042470..9e828030b 100644 --- a/shared/lib_battery_dispatch_automatic_fom.cpp +++ b/shared/lib_battery_dispatch_automatic_fom.cpp @@ -60,6 +60,7 @@ dispatch_automatic_front_of_meter_t::dispatch_automatic_front_of_meter_t( bool can_clip_charge, bool can_grid_charge, bool can_fuelcell_charge, + bool can_curtail_charge, double inverter_paco, std::vector battReplacementCostPerkWh, int battCycleCostChoice, @@ -71,7 +72,8 @@ dispatch_automatic_front_of_meter_t::dispatch_automatic_front_of_meter_t( double etaGridCharge, double etaDischarge, double interconnection_limit) : dispatch_automatic_t(Battery, dt_hour, SOC_min, SOC_max, current_choice, Ic_max, Id_max, Pc_max_kwdc, Pd_max_kwdc, Pc_max_kwac, Pd_max_kwac, - t_min, dispatch_mode, weather_forecast_mode, pv_dispatch, nyears, look_ahead_hours, dispatch_update_frequency_hours, can_charge, can_clip_charge, can_grid_charge, can_fuelcell_charge, + t_min, dispatch_mode, weather_forecast_mode, pv_dispatch, nyears, look_ahead_hours, dispatch_update_frequency_hours, + can_charge, can_clip_charge, can_grid_charge, can_fuelcell_charge, can_curtail_charge, battReplacementCostPerkWh, battCycleCostChoice, battCycleCost, battOMCost, interconnection_limit) { // if look behind, only allow 24 hours @@ -272,11 +274,18 @@ void dispatch_automatic_front_of_meter_t::update_dispatch(size_t year, size_t ho /*! Energy need to charge the battery (kWh) */ double energyNeededToFillBattery = _Battery->energy_to_fill(m_batteryPower->stateOfChargeMax); + // Positive: spare power to discharge. Negative: system power will be curtailed. Negative number can be fed directly into powerBattery to support charging + double interconnectionCapacity = std::fmin(m_batteryPower->powerInterconnectionLimit, m_batteryPower->powerCurtailmentLimit) - m_batteryPower->powerSystem; + /* Booleans to assist decisions */ bool highDischargeValuePeriod = ppa_cost >= discharge_ppa_cost && ppa_cost >= charge_ppa_cost; bool highChargeValuePeriod = ppa_cost <= charge_ppa_cost && ppa_cost <= discharge_ppa_cost; bool excessAcCapacity = _inverter_paco > m_batteryPower->powerSystemThroughSharedInverter; bool batteryHasDischargeCapacity = _Battery->SOC() >= m_batteryPower->stateOfChargeMin + 1.0; + bool interconnectionHasCapacity = interconnectionCapacity > 0.0; + bool canChargeFromCurtailedPower = interconnectionCapacity < 0.0 && (m_batteryPower->canCurtailCharge || m_batteryPower->canSystemCharge); + + revenueToCurtailCharge = canChargeFromCurtailedPower ? *max_ppa_cost * m_etaDischarge - m_cycleCost - m_omCost : 0; // Always Charge if PV is clipping if (m_batteryPower->canClipCharge && m_batteryPower->powerSystemClipped > 0 && revenueToClipCharge >= 0) @@ -284,6 +293,12 @@ void dispatch_automatic_front_of_meter_t::update_dispatch(size_t year, size_t ho powerBattery = -m_batteryPower->powerSystemClipped; } + // Always charge if system power is curtailed + if (canChargeFromCurtailedPower && revenueToCurtailCharge >= 0) { + // powerBattery is DC. Convert from AC to DC units to maximize utilization + powerBattery = interconnectionCapacity * m_batteryPower->singlePointEfficiencyACToDC; + } + // Increase charge from system (PV) if it is more valuable later than selling now if (m_batteryPower->canSystemCharge && revenueToPVCharge > 0 && @@ -332,7 +347,7 @@ void dispatch_automatic_front_of_meter_t::update_dispatch(size_t year, size_t ho } // Discharge if we are in a high-price period and have battery and inverter capacity - if (highDischargeValuePeriod && revenueToDischarge > 0 && excessAcCapacity && batteryHasDischargeCapacity) { + if (highDischargeValuePeriod && revenueToDischarge > 0 && excessAcCapacity && batteryHasDischargeCapacity && interconnectionHasCapacity) { double loss_kw = _Battery->calculate_loss(m_batteryPower->powerBatteryTarget, lifetimeIndex); // Battery is responsible for covering discharge losses if (m_batteryPower->connectionMode == BatteryPower::DC_CONNECTED) { powerBattery = _inverter_paco + loss_kw - m_batteryPower->powerSystem; @@ -340,6 +355,7 @@ void dispatch_automatic_front_of_meter_t::update_dispatch(size_t year, size_t ho else { powerBattery = _inverter_paco; // AC connected battery is already maxed out by AC power limit, cannot increase dispatch to ccover losses } + powerBattery = std::fmin(powerBattery, interconnectionCapacity); } // save for extraction m_batteryPower->powerBatteryTarget = powerBattery; diff --git a/shared/lib_battery_dispatch_automatic_fom.h b/shared/lib_battery_dispatch_automatic_fom.h index c64c169dc..ee23663f2 100644 --- a/shared/lib_battery_dispatch_automatic_fom.h +++ b/shared/lib_battery_dispatch_automatic_fom.h @@ -70,6 +70,7 @@ class dispatch_automatic_front_of_meter_t : public dispatch_automatic_t bool can_clipcharge, bool can_grid_charge, bool can_fuelcell_charge, + bool can_curtail_charge, double inverter_paco, std::vector battReplacementCostPerkWh, int battCycleCostChoice, @@ -142,6 +143,7 @@ class dispatch_automatic_front_of_meter_t : public dispatch_automatic_t double revenueToGridCharge; double revenueToClipCharge; double revenueToDischarge; + double revenueToCurtailCharge; }; #endif // __LIB_BATTERY_DISPATCH_AUTOMATIC_FOM_H__ diff --git a/shared/lib_battery_dispatch_manual.cpp b/shared/lib_battery_dispatch_manual.cpp index ad3e53041..d9c038389 100644 --- a/shared/lib_battery_dispatch_manual.cpp +++ b/shared/lib_battery_dispatch_manual.cpp @@ -44,12 +44,12 @@ dispatch_manual_t::dispatch_manual_t(battery_t * Battery, double dt, double SOC_ double t_min, int mode, int battMeterPosition, util::matrix_t dm_dynamic_sched, util::matrix_t dm_dynamic_sched_weekend, std::vector dm_charge, std::vector dm_discharge, std::vector dm_gridcharge, std::vector dm_fuelcellcharge, std::vector dm_btm_to_grid, - std::map dm_percent_discharge, std::map dm_percent_gridcharge, bool can_clip_charge, double interconnection_limit, + std::map dm_percent_discharge, std::map dm_percent_gridcharge, bool can_clip_charge, bool can_curtail_charge, double interconnection_limit, bool chargeOnlySystemExceedLoad, bool dischargeOnlyLoadExceedSystem, double SOC_min_outage, bool priorityChargeBattery) : dispatch_t(Battery, dt, SOC_min, SOC_max, current_choice, Ic_max, Id_max, Pc_max_kwdc, Pd_max_kwdc, Pc_max_kwac, Pd_max_kwac, t_min, mode, battMeterPosition, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, SOC_min_outage) { - init_with_vects(dm_dynamic_sched, dm_dynamic_sched_weekend, dm_charge, dm_discharge, dm_gridcharge, dm_fuelcellcharge, dm_btm_to_grid, dm_percent_discharge, dm_percent_gridcharge, can_clip_charge, priorityChargeBattery); + init_with_vects(dm_dynamic_sched, dm_dynamic_sched_weekend, dm_charge, dm_discharge, dm_gridcharge, dm_fuelcellcharge, dm_btm_to_grid, dm_percent_discharge, dm_percent_gridcharge, can_clip_charge, can_curtail_charge, priorityChargeBattery); } void dispatch_manual_t::init_with_vects( @@ -63,6 +63,7 @@ void dispatch_manual_t::init_with_vects( std::map dm_percent_discharge, std::map dm_percent_gridcharge, bool can_clip_charge, + bool can_curtail_charge, bool priorityChargeBattery) { _sched = dm_dynamic_sched; @@ -75,6 +76,7 @@ void dispatch_manual_t::init_with_vects( _percent_discharge_array = dm_percent_discharge; _percent_charge_array = dm_percent_gridcharge; _can_clip_charge = can_clip_charge; + _can_curtail_charge = can_curtail_charge; _priority_charge_battery = priorityChargeBattery; } @@ -85,7 +87,7 @@ dispatch_t(dispatch) const dispatch_manual_t * tmp = dynamic_cast(&dispatch); init_with_vects(tmp->_sched, tmp->_sched_weekend, tmp->_charge_array, tmp->_discharge_array, tmp->_gridcharge_array, tmp->_fuelcellcharge_array, tmp->_discharge_grid_array, - tmp->_percent_discharge_array, tmp->_percent_charge_array, tmp->_can_clip_charge, tmp->_priority_charge_battery); + tmp->_percent_discharge_array, tmp->_percent_charge_array, tmp->_can_clip_charge, tmp->_can_curtail_charge, tmp->_priority_charge_battery); } // shallow copy from dispatch to this @@ -95,7 +97,7 @@ void dispatch_manual_t::copy(const dispatch_t * dispatch) const dispatch_manual_t * tmp = dynamic_cast(dispatch); init_with_vects(tmp->_sched, tmp->_sched_weekend, tmp->_charge_array, tmp->_discharge_array, tmp->_gridcharge_array, tmp->_fuelcellcharge_array, tmp->_discharge_grid_array, - tmp->_percent_discharge_array, tmp->_percent_charge_array, tmp->_can_clip_charge, tmp->_priority_charge_battery); + tmp->_percent_discharge_array, tmp->_percent_charge_array, tmp->_can_clip_charge, tmp->_can_curtail_charge, tmp->_priority_charge_battery); } void dispatch_manual_t::prepareDispatch(size_t hour_of_year, size_t ) @@ -115,6 +117,7 @@ void dispatch_manual_t::prepareDispatch(size_t hour_of_year, size_t ) m_batteryPower->canDischarge = _discharge_array[iprofile - 1]; m_batteryPower->canGridCharge = _gridcharge_array[iprofile - 1]; m_batteryPower->canClipCharge = _can_clip_charge; + m_batteryPower->canCurtailCharge = _can_curtail_charge; if (iprofile <= _fuelcellcharge_array.size()) { m_batteryPower->canFuelCellCharge = _fuelcellcharge_array[iprofile - 1]; @@ -128,7 +131,7 @@ void dispatch_manual_t::prepareDispatch(size_t hour_of_year, size_t ) _percent_charge = 0.; if (m_batteryPower->canDischarge){ _percent_discharge = _percent_discharge_array[iprofile]; } - if (m_batteryPower->canClipCharge || m_batteryPower->canSystemCharge || m_batteryPower->canFuelCellCharge){ _percent_charge = 100.; } + if (m_batteryPower->canCurtailCharge || m_batteryPower->canClipCharge || m_batteryPower->canSystemCharge || m_batteryPower->canFuelCellCharge){ _percent_charge = 100.; } if (m_batteryPower->canGridCharge){ _percent_charge = _percent_charge_array[iprofile]; } } void dispatch_manual_t::dispatch(size_t year, @@ -209,6 +212,13 @@ bool dispatch_manual_t::check_constraints(double &I, size_t count) else I -= (m_batteryPower->powerBatteryToGrid / std::abs(m_batteryPower->powerBatteryAC)) * std::abs(I); } + // Back off discharge if we're violating interconnection limits + else if (m_batteryPower->powerInterconnectionLoss > 0 && m_batteryPower->powerBatteryAC > 0) { + I -= m_batteryPower->powerInterconnectionLoss / std::abs(m_batteryPower->powerBatteryAC) * std::abs(I); + if (I < 0) { + I = 0.0; + } + } else iterate = false; diff --git a/shared/lib_battery_dispatch_manual.h b/shared/lib_battery_dispatch_manual.h index 1c185c209..06728145c 100644 --- a/shared/lib_battery_dispatch_manual.h +++ b/shared/lib_battery_dispatch_manual.h @@ -65,6 +65,7 @@ class dispatch_manual_t : public dispatch_t std::map dm_percent_discharge, std::map dm_percent_gridcharge, bool can_clip_charge, + bool can_curtail_charge, double interconnection_limit, bool chargeOnlySystemExceedLoad = true, bool dischargeOnlyLoadExceedSystem = true, @@ -100,6 +101,7 @@ class dispatch_manual_t : public dispatch_t std::map dm_percent_discharge, std::map dm_percent_gridcharge, bool can_clip_charge, + bool can_curtail_charge, bool priorityChargeBattery); void SOC_controller() override; @@ -114,6 +116,7 @@ class dispatch_manual_t : public dispatch_t std::vector _fuelcellcharge_array; std::vector _discharge_grid_array; bool _can_clip_charge; + bool _can_curtail_charge; bool _priority_charge_battery; double _percent_discharge; diff --git a/shared/lib_battery_dispatch_pvsmoothing_fom.cpp b/shared/lib_battery_dispatch_pvsmoothing_fom.cpp index bc9fc0000..ca1d22ef2 100644 --- a/shared/lib_battery_dispatch_pvsmoothing_fom.cpp +++ b/shared/lib_battery_dispatch_pvsmoothing_fom.cpp @@ -60,6 +60,7 @@ dispatch_pvsmoothing_front_of_meter_t::dispatch_pvsmoothing_front_of_meter_t( bool can_clip_charge, bool can_grid_charge, bool can_fuelcell_charge, + bool can_curtail_charge, double inverter_paco, std::vector battReplacementCostPerkWh, int battCycleCostChoice, @@ -86,7 +87,8 @@ dispatch_pvsmoothing_front_of_meter_t::dispatch_pvsmoothing_front_of_meter_t( double interconnection_limit ) : dispatch_automatic_t(Battery, dt_hour, SOC_min, SOC_max, current_choice, Ic_max, Id_max, Pc_max_kwdc, Pd_max_kwdc, Pc_max_kwac, Pd_max_kwac, - t_min, dispatch_mode, weather_forecast_mode, pv_dispatch, nyears, look_ahead_hours, dispatch_update_frequency_hours, can_charge, can_clip_charge, can_grid_charge, can_fuelcell_charge, + t_min, dispatch_mode, weather_forecast_mode, pv_dispatch, nyears, look_ahead_hours, dispatch_update_frequency_hours, + can_charge, can_clip_charge, can_grid_charge, can_fuelcell_charge, can_curtail_charge, battReplacementCostPerkWh, battCycleCostChoice, battCycleCost, battOMCost, interconnection_limit), m_batt_dispatch_pvs_nameplate_ac(batt_dispatch_pvs_nameplate_ac), m_batt_dispatch_pvs_ac_lb(batt_dispatch_pvs_ac_lb), diff --git a/shared/lib_battery_dispatch_pvsmoothing_fom.h b/shared/lib_battery_dispatch_pvsmoothing_fom.h index 29b9bc593..9fa120572 100644 --- a/shared/lib_battery_dispatch_pvsmoothing_fom.h +++ b/shared/lib_battery_dispatch_pvsmoothing_fom.h @@ -67,6 +67,7 @@ class dispatch_pvsmoothing_front_of_meter_t : public dispatch_automatic_t bool can_clipcharge, bool can_grid_charge, bool can_fuelcell_charge, + bool can_curtail_charge, double inverter_paco, std::vector battReplacementCostPerkWh, // required for base class int battCycleCostChoice, diff --git a/shared/lib_battery_powerflow.cpp b/shared/lib_battery_powerflow.cpp index 5a9b0ae08..883538bc7 100644 --- a/shared/lib_battery_powerflow.cpp +++ b/shared/lib_battery_powerflow.cpp @@ -94,6 +94,7 @@ BatteryPower::BatteryPower(double dtHour) : inverterEfficiencyCutoff(5), canSystemCharge(false), canClipCharge(false), + canCurtailCharge(false), canGridCharge(false), canDischarge(false), canDischargeToGrid(false), @@ -162,6 +163,7 @@ BatteryPower::BatteryPower(const BatteryPower& orig) { inverterEfficiencyCutoff = orig.inverterEfficiencyCutoff; canSystemCharge = orig.canSystemCharge; canClipCharge = orig.canClipCharge; + canCurtailCharge = orig.canCurtailCharge; canGridCharge = orig.canGridCharge; canDischarge = orig.canDischarge; canDischargeToGrid = orig.canDischargeToGrid; @@ -280,12 +282,20 @@ void BatteryPowerFlow::initialize(double stateOfCharge, bool systemPriorityCharg m_BatteryPower->powerBatteryDC = m_BatteryPower->powerBatteryDischargeMaxDC; } // Is there extra power from system - else if ((((m_BatteryPower->powerSystem > m_BatteryPower->powerLoad) || !m_BatteryPower->chargeOnlySystemExceedLoad) && m_BatteryPower->canSystemCharge) || m_BatteryPower->canGridCharge || m_BatteryPower->canClipCharge) + else if ((((m_BatteryPower->powerSystem > m_BatteryPower->powerLoad) || !m_BatteryPower->chargeOnlySystemExceedLoad) && m_BatteryPower->canSystemCharge) || m_BatteryPower->canGridCharge || m_BatteryPower->canClipCharge || m_BatteryPower->canCurtailCharge) { if (m_BatteryPower->canClipCharge) { m_BatteryPower->powerBatteryDC = -m_BatteryPower->powerSystemClipped; } + if (m_BatteryPower->canCurtailCharge) { + double interconnectionCapacity = std::fmin(m_BatteryPower->powerInterconnectionLimit, m_BatteryPower->powerCurtailmentLimit) - m_BatteryPower->powerSystem; + if (interconnectionCapacity < 0.0 ) + { + m_BatteryPower->powerBatteryDC = interconnectionCapacity * m_BatteryPower->singlePointEfficiencyACToDC; + } + } + if (m_BatteryPower->canSystemCharge) { if (systemPriorityCharge) { @@ -364,7 +374,7 @@ void BatteryPowerFlow::calculateACConnected() if (P_battery_ac <= 0) { // Test if battery is charging erroneously - if (!(m_BatteryPower->canSystemCharge || m_BatteryPower->canGridCharge || m_BatteryPower->canFuelCellCharge) && P_battery_ac < 0) { + if (!(m_BatteryPower->canSystemCharge || m_BatteryPower->canGridCharge || m_BatteryPower->canFuelCellCharge || m_BatteryPower->canCurtailCharge) && P_battery_ac < 0) { P_pv_to_batt_ac = P_grid_to_batt_ac = P_fuelcell_to_batt_ac = 0; P_battery_ac = 0; } @@ -381,7 +391,7 @@ void BatteryPowerFlow::calculateACConnected() } // Excess PV can go to battery, if PV can cover charging losses - if (m_BatteryPower->canSystemCharge) { + if (m_BatteryPower->canSystemCharge || m_BatteryPower->canCurtailCharge) { P_pv_to_batt_ac = std::abs(P_battery_ac); P_available_pv = P_pv_ac - P_pv_to_load_ac - P_system_loss_ac; if (P_pv_to_batt_ac > P_available_pv) @@ -606,6 +616,9 @@ void BatteryPowerFlow::calculateACConnected() P_grid_ac = 0; if (std::abs(P_crit_load_unmet_ac) < m_BatteryPower->tolerance) P_crit_load_unmet_ac = 0; + if (std::abs(P_interconnection_loss_ac) < m_BatteryPower->tolerance) { + P_interconnection_loss_ac = 0; + } // assign outputs m_BatteryPower->powerBatteryAC = P_battery_ac; @@ -699,7 +712,7 @@ void BatteryPowerFlow::calculateDCConnected() { // First check whether battery charging came from PV. // Assumes that if battery is charging and can charge from PV, that it will charge from PV before using the grid - if (m_BatteryPower->canSystemCharge || m_BatteryPower->canClipCharge) { + if (m_BatteryPower->canSystemCharge || m_BatteryPower->canClipCharge || m_BatteryPower->canCurtailCharge) { P_pv_to_batt_dc = std::abs(P_battery_dc); if (P_pv_to_batt_dc > P_pv_dc - P_system_loss_dc) { P_pv_to_batt_dc = P_pv_dc - P_system_loss_dc; @@ -1011,6 +1024,9 @@ void BatteryPowerFlow::calculateDCConnected() P_grid_ac = 0; if (std::abs(P_crit_load_unmet_ac) < m_BatteryPower->tolerance) P_crit_load_unmet_ac = 0; + if (std::abs(P_interconnection_loss_ac) < m_BatteryPower->tolerance) { + P_interconnection_loss_ac = 0; + } // assign outputs m_BatteryPower->singlePointEfficiencyDCToAC = efficiencyDCAC; diff --git a/shared/lib_battery_powerflow.h b/shared/lib_battery_powerflow.h index 10d0da630..5fbda57de 100644 --- a/shared/lib_battery_powerflow.h +++ b/shared/lib_battery_powerflow.h @@ -188,7 +188,7 @@ struct BatteryPower double powerBatteryDischargeMaxAC; ///< The maximum sustained power the battery can discharge (kWac) double powerSystemLoss; ///< The auxiliary power loss in the system (kW) double powerConversionLoss; ///< The power loss due to conversions in the battery power electronics (kW) - double powerInterconnectionLimit; ///< The size of the grid interconnection (kW). As of July 2021 only applies to discharging, should apply to charging & dispatch + double powerInterconnectionLimit; ///< The size of the grid interconnection (kW). double powerInterconnectionLoss; ///< The power loss due to interconnection limit, outage, or curtailment (kW) double powerCurtailmentLimit; ///< The curtailment limit for the current step (kW) double voltageSystem; ///< The system voltage @@ -214,6 +214,7 @@ struct BatteryPower bool canSystemCharge; ///< A boolean specifying whether the battery is allowed to charge from PV in the timestep bool canClipCharge; ///< A boolean specifying whether the battery is allowed to charge from otherwise clipped PV in the timestep + bool canCurtailCharge; ///< A boolean specifying whether the battery is allowed to charge from otherwise curtailed energy in the timestep bool canGridCharge; ///< A boolean specifying whether the battery is allowed to charge from the Grid in the timestep bool canDischarge; ///< A boolean specifying whether the battery is allowed to discharge in the timestep bool canDischargeToGrid; ///< A boolean specifying whether the battery is allowed to discharge to grid in the timestep diff --git a/ssc/cmod_battery.cpp b/ssc/cmod_battery.cpp index a0b895010..50b0a330b 100644 --- a/ssc/cmod_battery.cpp +++ b/ssc/cmod_battery.cpp @@ -167,6 +167,7 @@ var_info vtab_battery_inputs[] = { { 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", "", "", "" }, { SSC_INPUT, SSC_NUMBER, "batt_dispatch_auto_can_clipcharge", "Battery can charge from clipped power?", "0/1", "", "BatteryDispatch", "", "", "" }, + { SSC_INPUT, SSC_NUMBER, "batt_dispatch_auto_can_curtailcharge", "Battery can charge from grid-limited system power?", "0/1", "", "BatteryDispatch", "", "", "" }, { SSC_INPUT, SSC_NUMBER, "batt_dispatch_auto_btm_can_discharge_to_grid", "Behind the meter battery can discharge to grid?", "0/1", "", "BatteryDispatch", "", "", "" }, { SSC_INPUT, SSC_NUMBER, "batt_dispatch_charge_only_system_exceeds_load", "Battery can charge from system only when system output exceeds load", "0/1", "", "BatteryDispatch", "en_batt=1&en_standalone_batt=0&batt_meter_position=0", "", "" }, { SSC_INPUT, SSC_NUMBER, "batt_dispatch_discharge_only_load_exceeds_system","Battery can discharge battery only when load exceeds system output", "0/1", "", "BatteryDispatch", "en_batt=1&en_standalone_batt=0&batt_meter_position=0", "", "" }, @@ -746,6 +747,7 @@ battstor::battstor(var_table& vt, bool setup_model, size_t nrec, double dt_hr, c // Common to automated methods batt_vars->batt_dispatch_auto_can_charge = true; batt_vars->batt_dispatch_auto_can_clipcharge = false; + batt_vars->batt_dispatch_auto_can_curtailcharge = false; batt_vars->batt_dispatch_auto_can_gridcharge = false; batt_vars->batt_dispatch_auto_can_fuelcellcharge = true; batt_vars->batt_dispatch_auto_btm_can_discharge_to_grid = false; @@ -759,6 +761,9 @@ battstor::battstor(var_table& vt, bool setup_model, size_t nrec, double dt_hr, c if (vt.is_assigned("batt_dispatch_auto_can_clipcharge")) { batt_vars->batt_dispatch_auto_can_clipcharge = vt.as_boolean("batt_dispatch_auto_can_clipcharge"); } + if (vt.is_assigned("batt_dispatch_auto_can_curtailcharge")) { + batt_vars->batt_dispatch_auto_can_curtailcharge = vt.as_boolean("batt_dispatch_auto_can_curtailcharge"); + } if (vt.is_assigned("batt_dispatch_auto_can_fuelcellcharge")) { batt_vars->batt_dispatch_auto_can_fuelcellcharge = vt.as_boolean("batt_dispatch_auto_can_fuelcellcharge"); } @@ -1263,7 +1268,7 @@ battstor::battstor(var_table& vt, bool setup_model, size_t nrec, double dt_hr, c batt_vars->batt_dispatch, batt_vars->batt_meter_position, batt_vars->batt_discharge_schedule_weekday, batt_vars->batt_discharge_schedule_weekend, batt_vars->batt_can_charge, batt_vars->batt_can_discharge, batt_vars->batt_can_gridcharge, batt_vars->batt_can_fuelcellcharge, batt_vars->batt_btm_can_discharge_to_grid, - dm_percent_discharge, dm_percent_gridcharge, batt_vars->batt_dispatch_auto_can_clipcharge, batt_vars->grid_interconnection_limit_kW, + dm_percent_discharge, dm_percent_gridcharge, batt_vars->batt_dispatch_auto_can_clipcharge, batt_vars->batt_dispatch_auto_can_curtailcharge, batt_vars->grid_interconnection_limit_kW, batt_vars->batt_dispatch_charge_only_system_exceeds_load, batt_vars->batt_dispatch_discharge_only_load_exceeds_system, batt_vars->batt_minimum_outage_SOC, @@ -1296,7 +1301,8 @@ battstor::battstor(var_table& vt, bool setup_model, size_t nrec, double dt_hr, c batt_vars->batt_minimum_modetime, batt_vars->batt_dispatch, batt_vars->batt_dispatch_wf_forecast, batt_vars->batt_meter_position, nyears, batt_vars->batt_look_ahead_hours, batt_vars->batt_dispatch_update_frequency_hours, - batt_vars->batt_dispatch_auto_can_charge, batt_vars->batt_dispatch_auto_can_clipcharge, batt_vars->batt_dispatch_auto_can_gridcharge, batt_vars->batt_dispatch_auto_can_fuelcellcharge, + batt_vars->batt_dispatch_auto_can_charge, batt_vars->batt_dispatch_auto_can_clipcharge, batt_vars->batt_dispatch_auto_can_gridcharge, + batt_vars->batt_dispatch_auto_can_fuelcellcharge, batt_vars->batt_dispatch_auto_can_curtailcharge, batt_vars->inverter_paco, batt_vars->batt_cost_per_kwh, batt_vars->batt_cycle_cost_choice, batt_vars->batt_cycle_cost, batt_vars->om_batt_variable_cost_per_kwh, eta_pvcharge, eta_gridcharge, eta_discharge, batt_vars->batt_dispatch_pvs_nameplate_ac, @@ -1315,7 +1321,8 @@ battstor::battstor(var_table& vt, bool setup_model, size_t nrec, double dt_hr, c batt_vars->batt_minimum_modetime, batt_vars->batt_dispatch, batt_vars->batt_dispatch_wf_forecast, batt_vars->batt_meter_position, nyears, batt_vars->batt_look_ahead_hours, batt_vars->batt_dispatch_update_frequency_hours, - batt_vars->batt_dispatch_auto_can_charge, batt_vars->batt_dispatch_auto_can_clipcharge, batt_vars->batt_dispatch_auto_can_gridcharge, batt_vars->batt_dispatch_auto_can_fuelcellcharge, + batt_vars->batt_dispatch_auto_can_charge, batt_vars->batt_dispatch_auto_can_clipcharge, batt_vars->batt_dispatch_auto_can_gridcharge, + batt_vars->batt_dispatch_auto_can_fuelcellcharge, batt_vars->batt_dispatch_auto_can_curtailcharge, batt_vars->inverter_paco, batt_vars->batt_cost_per_kwh, batt_vars->batt_cycle_cost_choice, batt_vars->batt_cycle_cost, batt_vars->om_batt_variable_cost_per_kwh, batt_vars->forecast_price_series_dollar_per_kwh, utilityRate, @@ -1350,7 +1357,8 @@ battstor::battstor(var_table& vt, bool setup_model, size_t nrec, double dt_hr, c batt_vars->batt_minimum_modetime, batt_vars->batt_dispatch, batt_vars->batt_dispatch_wf_forecast, batt_vars->batt_meter_position, nyears, batt_vars->batt_look_ahead_hours, batt_vars->batt_dispatch_update_frequency_hours, - batt_vars->batt_dispatch_auto_can_charge, batt_vars->batt_dispatch_auto_can_clipcharge, batt_vars->batt_dispatch_auto_can_gridcharge, batt_vars->batt_dispatch_auto_can_fuelcellcharge, + batt_vars->batt_dispatch_auto_can_charge, batt_vars->batt_dispatch_auto_can_clipcharge, batt_vars->batt_dispatch_auto_can_gridcharge, + batt_vars->batt_dispatch_auto_can_fuelcellcharge, batt_vars->batt_dispatch_auto_can_curtailcharge, util_rate_data, batt_vars->batt_cost_per_kwh, batt_vars->batt_cycle_cost_choice, batt_vars->batt_cycle_cost, batt_vars->om_batt_variable_cost_per_kwh, batt_vars->grid_interconnection_limit_kW, batt_vars->batt_dispatch_charge_only_system_exceeds_load, batt_vars->batt_dispatch_discharge_only_load_exceeds_system, batt_vars->batt_dispatch_auto_btm_can_discharge_to_grid, batt_vars->batt_minimum_outage_SOC, batt_vars->batt_dispatch_load_forecast diff --git a/ssc/cmod_battery.h b/ssc/cmod_battery.h index 3909b05c3..a1d4cacf8 100644 --- a/ssc/cmod_battery.h +++ b/ssc/cmod_battery.h @@ -89,6 +89,9 @@ struct batt_variables /*! Determines if the battery is allowed to charge from PV clipping using automated control*/ bool batt_dispatch_auto_can_clipcharge; + /*! Determines if the battery is allowed to charge from curtailed energy using automated control*/ + bool batt_dispatch_auto_can_curtailcharge; + /*! Determines if the battery is allowed to charge from fuel cell using automated control*/ bool batt_dispatch_auto_can_fuelcellcharge; 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 fd290c3b0..07fdde8e2 100644 --- a/test/shared_test/lib_battery_dispatch_automatic_btm_test.cpp +++ b/test/shared_test/lib_battery_dispatch_automatic_btm_test.cpp @@ -44,7 +44,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMGridCharging) { max_current, max_current, max_power, max_power, max_power, max_power, 0, dispatch_t::BTM_MODES::PEAK_SHAVING, 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, + true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); // Setup pv and load signal for peak shaving algorithm @@ -92,7 +92,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMPVCharging) { max_current, max_current, max_power, max_power, max_power, max_power, 0, dispatch_t::BTM_MODES::PEAK_SHAVING, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, 0, 1, 24, 1, true, - true, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, + true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); // Setup pv and load signal for peak shaving algorithm @@ -136,7 +136,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMPVChargeAndDischarge) { max_current, max_current, max_power, max_power, max_power, max_power, 0, dispatch_t::BTM_MODES::PEAK_SHAVING, 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, + true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); // Setup pv and load signal for peak shaving algorithm for (size_t h = 0; h < 24; h++) { @@ -187,7 +187,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMPVChargeAndDischargeSubh max_current, max_current, max_power, max_power, max_power, max_power, 0, dispatch_t::BTM_MODES::PEAK_SHAVING, 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, + true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); // Setup pv and load signal for peak shaving algorithm @@ -255,7 +255,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMDCClipCharge) { max_current, max_current, max_power, max_power, max_power, max_power, 0, dispatch_t::BTM_MODES::PEAK_SHAVING, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, 0, 1, 24, 1, - false, true, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, + false, true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); // Setup pv and load signal for peak shaving algorithm @@ -309,7 +309,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, TestBasicForecast) { max_current, max_current, max_power, max_power, max_power, max_power, 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, + true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); // Setup pv and load signal for peak shaving algorithm @@ -365,7 +365,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, TestSummerPeak) { max_current, max_current, max_power, max_power, max_power, max_power, 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, + true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); load_prediction = { 1.44289, 1.27067, 1.1681, 1.09342, 1.12921, 1.39345, 1.57299, 1.63055, 1.85622, 2.44991, 2.61812, 2.90909, 3.29601, 3.64366, 3.88232, 3.99237, 4.09673, 4.11102, 4.09175, 4.13445, 3.91011, 3.27815, 2.67845, 2.11802, 1.78025, 1.57142, 1.42908, 1.32466, @@ -405,7 +405,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, TestSummerPeakNetMeteringCredits) { max_current, max_current, max_power, max_power, max_power, max_power, 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, + true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); load_prediction = { 1.44289, 1.27067, 1.1681, 1.09342, 1.12921, 1.39345, 1.57299, 1.63055, 1.85622, 2.44991, 2.61812, 2.90909, 3.29601, 3.64366, 3.88232, 3.99237, 4.09673, 4.11102, 4.09175, 4.13445, 3.91011, 3.27815, 2.67845, 2.11802, 1.78025, 1.57142, 1.42908, 1.32466, @@ -445,7 +445,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, TestSummerPeakGridCharging) { max_current, max_current, max_power, max_power, max_power, max_power, 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, + true, canGridCharge, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); load_prediction = { 1.44289, 1.27067, 1.1681, 1.09342, 1.12921, 1.39345, 1.57299, 1.63055, 1.85622, 2.44991, 2.61812, 2.90909, 3.29601, 3.64366, 3.88232, 3.99237, 4.09673, 4.11102, 4.09175, 4.13445, 3.91011, 3.27815, 2.67845, 2.11802, 1.78025, 1.57142, 1.42908, 1.32466, @@ -486,7 +486,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, TestSummerPeakGridChargingSubhourly) { max_current, max_current, max_power, max_power, max_power, max_power, 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, + true, canGridCharge, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); load_prediction = { 1.44289, 1.27067, 1.1681, 1.09342, 1.12921, 1.39345, 1.57299, 1.63055, 1.85622, 2.44991, 2.61812, 2.90909, 3.29601, 3.64366, 3.88232, 3.99237, 4.09673, 4.11102, 4.09175, 4.13445, 3.91011, 3.27815, 2.67845, 2.11802, 1.78025, 1.57142, 1.42908, 1.32466, @@ -540,7 +540,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, TestCommercialPeakForecasting) { max_current, max_current, max_power, max_power, max_power, max_power, 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, + 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); load_prediction = { 49.9898, 42.4037, 42.1935, 43.3778, 39.4545, 59.3723, 84.6907, 180.423, 180.836, 186.225, 197.275, 205.302, 231.362, @@ -584,7 +584,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMPVChargeAndDischargeSmal max_current, max_current, max_power, max_power, max_power, max_power, 0, dispatch_t::BTM_MODES::PEAK_SHAVING, 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, + true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); // Setup pv and load signal for peak shaving algorithm @@ -637,7 +637,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMPVChargeAndDischargeSmal max_current, max_current, max_power, max_power, max_power, max_power, 0, dispatch_t::BTM_MODES::PEAK_SHAVING, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, 0, 1, 24, 1, true, - true, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, + true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); // Setup pv and load signal for peak shaving algorithm @@ -690,7 +690,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMCustomDispatch) { max_current, max_current, max_power, max_power, max_power, max_power, 0, dispatch_t::BTM_MODES::CUSTOM_DISPATCH, 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, + true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); // Setup custom dispatch signal - signal and expected AC power are the same without losses @@ -726,7 +726,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMCustomDispatchDischargeT max_current, max_current, max_power, max_power, max_power, max_power , 0, dispatch_t::BTM_MODES::CUSTOM_DISPATCH, 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, + true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); // Setup custom dispatch signal - signal and expected AC power are the same without losses. Load is 40 kW, so this will exceed load by 8 kW @@ -760,7 +760,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMCustomDispatchWithLosses max_current, max_current, max_power, max_power, max_power, max_power, 0, dispatch_t::BTM_MODES::CUSTOM_DISPATCH, 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, + true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); // Setup custom dispatch signal - need to account for losses when discharging @@ -796,7 +796,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMCustomWExcessPV) { max_current, max_current, max_power, max_power, max_power, max_power, 0, dispatch_t::BTM_MODES::CUSTOM_DISPATCH, 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, + true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); // Setup custom dispatch signal - signal is greater than expected power since constraints should prevent dispatch hours 13 through 17 @@ -838,7 +838,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMGridOutagePeakShavingDai max_current, max_current, max_power * defaultEff, max_power / defaultEff, max_power, max_power, 0, dispatch_t::BTM_MODES::PEAK_SHAVING, 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, + true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); // Setup pv and load signal for peak shaving algorithm @@ -908,7 +908,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMGridOutageWithAvailabili max_current, max_current, max_power * defaultEff, max_power / defaultEff, max_power, max_power, 0, dispatch_t::BTM_MODES::PEAK_SHAVING, 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, + true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); // Setup pv and load signal for peak shaving algorithm @@ -979,7 +979,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMGridOutageWithAvailabili max_current, max_current, max_power * defaultEff, max_power / defaultEff, max_power, max_power, 0, dispatch_t::BTM_MODES::PEAK_SHAVING, 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, + true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); // Setup pv and load signal for peak shaving algorithm @@ -1051,7 +1051,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMGridOutageWithInverterLo max_current, max_current, max_power * defaultEff, max_power / defaultEff, max_power, max_power, 0, dispatch_t::BTM_MODES::PEAK_SHAVING, 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, + true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); // Setup pv and load signal for peak shaving algorithm @@ -1124,7 +1124,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMGridOutagePeakShavingEmp max_current, max_current, max_power * defaultEff, max_power / defaultEff, max_power, max_power, 0, dispatch_t::BTM_MODES::PEAK_SHAVING, 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, + true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); // Setup pv and load signal for peak shaving algorithm @@ -1242,7 +1242,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMGridOutageRetailRAteEmpt max_current, max_current, max_power * defaultEff, max_power / defaultEff, max_power, max_power, 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, + true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); // Setup pv and load signal for peak shaving algorithm @@ -1362,7 +1362,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMGridOutageCustomEmptyAnd max_current, max_current, max_power * defaultEff, max_power / defaultEff, max_power, max_power, 0, dispatch_t::BTM_MODES::CUSTOM_DISPATCH, 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, + true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); // Setup pv and load signal for peak shaving algorithm @@ -1484,7 +1484,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMGridOutagePeakShavingDC) max_current, max_current, max_power * defaultEff, max_power / defaultEff, max_power, max_power, 0, dispatch_t::BTM_MODES::PEAK_SHAVING, 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, + true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); // Setup pv and load signal for peak shaving algorithm @@ -1554,7 +1554,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMGridOutageFuelCellCharge max_current, max_current, max_power * defaultEff, max_power / defaultEff, max_power, max_power, 0, dispatch_t::BTM_MODES::PEAK_SHAVING, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, 0, 1, 24, 1, true, - true, false, true, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, + true, false, true, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); // Setup pv and load signal for peak shaving algorithm @@ -1635,7 +1635,7 @@ TEST_F(AutoBTMTest_lib_battery_dispatch, DispatchAutoBTMSetupRateForecastMultiYe max_current, max_current, max_power * defaultEff, max_power / defaultEff, max_power, max_power, 0, dispatch_t::BTM_MODES::RETAIL_RATE, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, 0, nyears, 24, 1, true, - true, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, + true, false, false, false, util_rate, replacementCost, cyclingChoice, cyclingCost, omCost, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, dischargeToGrid, min_outage_soc, dispatch_t::LOAD_FORECAST_CHOICE::LOAD_LOOK_AHEAD); // Setup pv and load signal for peak shaving algorithm diff --git a/test/shared_test/lib_battery_dispatch_automatic_fom_test.cpp b/test/shared_test/lib_battery_dispatch_automatic_fom_test.cpp index 13fd5f1b7..082a97cea 100644 --- a/test/shared_test/lib_battery_dispatch_automatic_fom_test.cpp +++ b/test/shared_test/lib_battery_dispatch_automatic_fom_test.cpp @@ -38,7 +38,7 @@ TEST_F(AutoFOM_lib_battery_dispatch, DispatchFOMInput) { double dtHourFOM = 1.0; CreateBattery(dtHourFOM); dispatchAuto = new dispatch_automatic_front_of_meter_t(batteryModel, dtHourFOM, 15, 95, 1, 999, 999, max_power, max_power, - max_power, max_power, 1, dispatch_t::FOM_CUSTOM_DISPATCH, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, dispatch_t::FRONT, 1, 24, 1, true, true, false, true, 0, + max_power, max_power, 1, dispatch_t::FOM_CUSTOM_DISPATCH, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, dispatch_t::FRONT, 1, 24, 1, true, true, false, true, false, 0, replacementCost, 0, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); std::vector P_batt = {-336.062, 336.062}; @@ -74,7 +74,7 @@ TEST_F(AutoFOM_lib_battery_dispatch, DispatchFOMInputWithLosses) { double dtHourFOM = 1.0; CreateBatteryWithLosses(dtHourFOM); dispatchAuto = new dispatch_automatic_front_of_meter_t(batteryModel, dtHourFOM, 15, 95, 1, 999, 999, max_power, max_power, - max_power, max_power, 1, dispatch_t::FOM_CUSTOM_DISPATCH, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, dispatch_t::FRONT, 1, 24, 1, true, true, false, true, 0, + max_power, max_power, 1, dispatch_t::FOM_CUSTOM_DISPATCH, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, dispatch_t::FRONT, 1, 24, 1, true, true, false, true, false, 0, replacementCost, 0, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); std::vector P_batt = { -336.062, 336.062 }; @@ -112,7 +112,7 @@ TEST_F(AutoFOM_lib_battery_dispatch, DispatchFOMInputSubhourly) { double dtHourFOM = 0.5; CreateBattery(dtHourFOM); dispatchAuto = new dispatch_automatic_front_of_meter_t(batteryModel, dtHourFOM, 15, 95, 1, 999, 999, max_power, max_power, - max_power, max_power, 1, dispatch_t::FOM_CUSTOM_DISPATCH, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, dispatch_t::FRONT, 1, 24, 1, true, true, false, true, 0, + max_power, max_power, 1, dispatch_t::FOM_CUSTOM_DISPATCH, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, dispatch_t::FRONT, 1, 24, 1, true, true, false, true, false, 0, replacementCost, 0, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); std::vector P_batt = {-336.062, 336.062}; @@ -149,7 +149,7 @@ TEST_F(AutoFOM_lib_battery_dispatch, DispatchFOM_DCCustomCharge) { CreateBattery(dtHour); dispatchAuto = new dispatch_automatic_front_of_meter_t(batteryModel, dtHour, 10, 100, 1, 49960, 49960, max_power, max_power, max_power, max_power, 1, dispatch_t::FOM_CUSTOM_DISPATCH, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, dispatch_t::FRONT, 1, 18, 1, true, - true, true, false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, + true, true, false, false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); std::vector P_batt(6, -25000); @@ -201,7 +201,7 @@ TEST_F(AutoFOM_lib_battery_dispatch, DispatchFOM_DCCustomChargeSubhourly) { CreateBattery(dtHour); dispatchAuto = new dispatch_automatic_front_of_meter_t(batteryModel, dtHour, 10, 100, 1, 49960, 49960, max_power, max_power, max_power, max_power, 1, dispatch_t::FOM_CUSTOM_DISPATCH, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, dispatch_t::FRONT, 1, 18, 1, true, - true, true, false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, + true, true, false, false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); std::vector P_batt(12, -25000); @@ -256,7 +256,7 @@ TEST_F(AutoFOM_lib_battery_dispatch, DispatchFOM_DCAuto) { CreateBattery(dtHour); dispatchAuto = new dispatch_automatic_front_of_meter_t(batteryModel, dtHour, 10, 100, 1, 49960, 49960, max_power, max_power, max_power, max_power, 1, dispatch_t::FOM_AUTOMATED_ECONOMIC, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, dispatch_t::FRONT, 1, 18, 1, true, true, false, - false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); + false, false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); // battery setup dispatchAuto->update_pv_data(pv); @@ -298,7 +298,7 @@ TEST_F(AutoFOM_lib_battery_dispatch, DispatchFOM_DCAutoWithLosses) { CreateBatteryWithLosses(dtHour); dispatchAuto = new dispatch_automatic_front_of_meter_t(batteryModel, dtHour, 10, 100, 1, 49960, 49960, max_power, max_power, max_power, max_power, 1, dispatch_t::FOM_AUTOMATED_ECONOMIC, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, dispatch_t::FRONT, 1, 18, 1, true, true, false, - false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); + false, false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); // battery setup dispatchAuto->update_pv_data(pv); @@ -339,7 +339,7 @@ TEST_F(AutoFOM_lib_battery_dispatch, DispatchFOM_DCAutoSubhourly) { CreateBattery(dtHour); dispatchAuto = new dispatch_automatic_front_of_meter_t(batteryModel, dtHour, 10, 100, 1, 49960, 49960, max_power, max_power, max_power, max_power, 1, dispatch_t::FOM_AUTOMATED_ECONOMIC, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, dispatch_t::FRONT, 1, 18, 1, true, true, false, - false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); + false, false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); // battery setup dispatchAuto->update_pv_data(pv); @@ -375,7 +375,7 @@ TEST_F(AutoFOM_lib_battery_dispatch, DispatchFOM_ACCustomCharge) { CreateBattery(dtHour); dispatchAuto = new dispatch_automatic_front_of_meter_t(batteryModel, dtHour, 10, 100, 1, 49960, 49960, max_power, max_power, max_power, max_power, 1, dispatch_t::FOM_CUSTOM_DISPATCH, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, dispatch_t::FRONT, 1, 18, 1, true, - true, true, false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, + true, true, false, false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); std::vector P_batt(6, -25000); @@ -426,7 +426,7 @@ TEST_F(AutoFOM_lib_battery_dispatch, DispatchFOM_ACCustomChargeSubhourly) { CreateBattery(dtHour); dispatchAuto = new dispatch_automatic_front_of_meter_t(batteryModel, dtHour, 10, 100, 1, 49960, 49960, max_power, max_power, max_power, max_power, 1, dispatch_t::FOM_CUSTOM_DISPATCH, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, dispatch_t::FRONT, 1, 18, 1, true, - true, true, false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, + true, true, false, false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); std::vector P_batt(12, -25000); @@ -480,7 +480,7 @@ TEST_F(AutoFOM_lib_battery_dispatch, DispatchFOM_ACAuto) { CreateBattery(dtHour); dispatchAuto = new dispatch_automatic_front_of_meter_t(batteryModel, dtHour, 10, 100, 1, 49960, 49960, max_power, max_power, max_power, max_power, 1, dispatch_t::FOM_AUTOMATED_ECONOMIC, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, dispatch_t::FRONT, 1, 18, 1, true, true, false, - false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); + false, false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); // battery setup dispatchAuto->update_pv_data(pv); // PV Resource is available for the 1st 10 hrs @@ -523,7 +523,7 @@ TEST_F(AutoFOM_lib_battery_dispatch, DispatchFOM_ACAutoWithLosses) { CreateBatteryWithLosses(dtHour); dispatchAuto = new dispatch_automatic_front_of_meter_t(batteryModel, dtHour, 10, 100, 1, 49960, 49960, max_power, max_power, max_power, max_power, 1, dispatch_t::FOM_AUTOMATED_ECONOMIC, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, dispatch_t::FRONT, 1, 18, 1, true, true, false, - false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); + false, false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); // battery setup dispatchAuto->update_pv_data(pv); // PV Resource is available for the 1st 10 hrs @@ -566,7 +566,7 @@ TEST_F(AutoFOM_lib_battery_dispatch, DispatchFOM_ACAutoSubhourly) { CreateBattery(dtHour); dispatchAuto = new dispatch_automatic_front_of_meter_t(batteryModel, dtHour, 10, 100, 1, 49960, 49960, max_power, max_power, max_power, max_power, 1, dispatch_t::FOM_AUTOMATED_ECONOMIC, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, dispatch_t::FRONT, 1, 18, 1, true, true, false, - false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); + false, false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); // battery setup dispatchAuto->update_pv_data(pv); @@ -624,7 +624,7 @@ TEST_F(AutoFOM_lib_battery_dispatch, DispatchFOM_DCAuto_ClipChargeFlatRate) { dispatchAuto = new dispatch_automatic_front_of_meter_t(batteryModel, dtHour, 10, 100, 1, 49960, 49960, max_power, max_power, max_power, max_power, 1, dispatch_t::FOM_AUTOMATED_ECONOMIC, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, dispatch_t::FRONT, 1, 18, 1, true, true, false, - false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); + false, false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); // battery setup dispatchAuto->update_pv_data(pv); @@ -664,3 +664,91 @@ TEST_F(AutoFOM_lib_battery_dispatch, DispatchFOM_DCAuto_ClipChargeFlatRate) { } } + +TEST_F(AutoFOM_lib_battery_dispatch, DispatchFOM_DCAutoWithInterconnectionLimit) { + double dtHour = 1; + CreateBattery(dtHour); + interconnection_limit = 50000; + dispatchAuto = new dispatch_automatic_front_of_meter_t(batteryModel, dtHour, 10, 100, 1, 49960, 49960, max_power, + max_power, max_power, max_power, 1, dispatch_t::FOM_AUTOMATED_ECONOMIC, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, dispatch_t::FRONT, 1, 18, 1, true, true, false, + false, false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); + + // battery setup + dispatchAuto->update_pv_data(pv); + dispatchAuto->update_cliploss_data(clip); + batteryPower = dispatchAuto->getBatteryPower(); + batteryPower->connectionMode = ChargeController::DC_CONNECTED; + batteryPower->voltageSystem = 600; + batteryPower->setSharedInverter(m_sharedInverter); + + std::vector targetkW = { 28396.7, -19294.27, 5515.3, -35296.51, -35570.30, -34754.11, // 0 - 5 + -12969.9, -1797.387, -250.22, -35.16, 0., 0., // 6 - 11 + 0., 0., 0., 0., 0., 50000, // 12 - 17 + 50000, 50000, 50000, 50000, 50000, 0. }; // 18 - 23 + std::vector dispatchedkW = { 27100.68, -19294.27, 5515.3, -28862.56, -29079.57, -29217.40, // 0 - 5 + -12969.9, -1797.387, -250.22, -35.16, 0., 0., // 6 - 11 + 0., 0., 0., 0., 0., 28116.27, // 18 + 27947.03, 27664.92, 27100.53, 25407.36, 9381.21, 0. }; // 24 + std::vector SOC = { 33.33, 44.65, 41.35, 58.02, 74.68, 91.35, // 0 - 5 + 98.8, 99.8, 99.97, 99.99, 99.99, 99.99, // 6 - 11 + 99.99, 99.99, 99.99, 99.99, 99.99, 83.33, // 12 - 17 + 66.66, 50.0, 33.33, 16.66, 10.0, 10.0 }; // 18 - 23 + for (size_t h = 0; h < 24; h++) { + batteryPower->powerGeneratedBySystem = pv[h]; + batteryPower->powerSystem = pv[h]; + batteryPower->powerSystemClipped = clip[h]; + + dispatchAuto->update_dispatch(0, h, 0, h); + EXPECT_NEAR(batteryPower->powerBatteryTarget, targetkW[h], 0.1) << "error in expected target at hour " << h; + + dispatchAuto->dispatch(0, h, 0); + EXPECT_NEAR(batteryPower->powerBatteryDC, dispatchedkW[h], 0.1) << "error in dispatched power at hour " << h; + EXPECT_NEAR(dispatchAuto->battery_soc(), SOC[h], 0.1) << "error in SOC at hour " << h; + + } +} + +TEST_F(AutoFOM_lib_battery_dispatch, DispatchFOM_ACAutoWithInterconnectionLimit) { + double dtHour = 1; + CreateBattery(dtHour); + interconnection_limit = 50000; + dispatchAuto = new dispatch_automatic_front_of_meter_t(batteryModel, dtHour, 10, 100, 1, 49960, 49960, max_power, + max_power, max_power, max_power, 1, dispatch_t::FOM_AUTOMATED_ECONOMIC, dispatch_t::WEATHER_FORECAST_CHOICE::WF_LOOK_AHEAD, dispatch_t::FRONT, 1, 18, 1, true, false, false, + false, false, 77000, replacementCost, 1, cyclingCost, omCost, ppaRate, ur, 98, 98, 98, interconnection_limit); + + // battery setup + dispatchAuto->update_pv_data(pv); // PV Resource is available for the 1st 10 hrs + dispatchAuto->update_cliploss_data(clip); // Clip charging is available for the 1st 5 hrs + batteryPower = dispatchAuto->getBatteryPower(); + batteryPower->connectionMode = ChargeController::AC_CONNECTED; + batteryPower->voltageSystem = 600; + batteryPower->setSharedInverter(m_sharedInverter); + + // A few hours at the beginnging flip from discharge to charge since the PV will be curtailed + // Note on hour 3: the price here is both the 2nd highest price and the 2nd lowest price. A non-zero replacement cost could prevent cycling here. + std::vector targetkW = { 28396.7, -19294.27, 5515.3, -35296.51, -35570.30, -34754.11, // 0 - 5 + -84205.39, -78854.6, -67702.19, -31516.09, 0., 0., // 6 - 11 + 0., 0., 0., 0., 0., 50000, // 12 - 17 + 50000, 50000, 50000, 50000, 50000, 0. }; // 18 - 23 + std::vector dispatchedkW = { 27100.68, -19294.27, 5515.3, -28862.56, -29079.57, -29217.40, // 0 - 5 + -15235.74, 0.0, 0.0, 0.0, 0., 0.,// 6 - 11 + 0., 0., 0., 0., 0., 28116.30, // 12 - 17 + 27947.03, 27664.92, 27100.69, 25408.03, 9385.81, 0. }; // 18 - 23 + std::vector SOC = { 33.3, 44.65, 41.35, 58.02, 74.68, 91.35, // 0 - 5 + 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, // 6 - 11 + 100.0, 100.0, 100.0, 100.0, 100.0, 83.33, // 12 - 17 + 66.66, 50.0, 33.33, 16.66, 10.0, 10.0 }; // 18 - 23 + for (size_t h = 0; h < 24; h++) { + batteryPower->powerGeneratedBySystem = pv[h]; + batteryPower->powerSystem = pv[h]; + batteryPower->powerSystemClipped = clip[h]; + + dispatchAuto->update_dispatch(0, h, 0, h); + EXPECT_NEAR(batteryPower->powerBatteryTarget, targetkW[h], 0.1) << "error in expected target at hour " << h; + + dispatchAuto->dispatch(0, h, 0); + + EXPECT_NEAR(batteryPower->powerBatteryDC, dispatchedkW[h], 0.1) << "error in dispatched power at hour " << h; + EXPECT_NEAR(dispatchAuto->battery_soc(), SOC[h], 0.1) << "error in SOC at hour " << h; + } +} diff --git a/test/shared_test/lib_battery_dispatch_manual_test.cpp b/test/shared_test/lib_battery_dispatch_manual_test.cpp index 715fdb89a..ce8b1f33a 100644 --- a/test/shared_test/lib_battery_dispatch_manual_test.cpp +++ b/test/shared_test/lib_battery_dispatch_manual_test.cpp @@ -43,7 +43,7 @@ TEST_F(ManualTest_lib_battery_dispatch, PowerLimitsDispatchManualAC) { powerDischargeMax, minimumModeTime, dispatchChoice, meterPosition, scheduleWeekday, scheduleWeekend, canCharge, canDischarge, canGridcharge, canDischargeToGrid, canGridcharge, percentDischarge, - percentGridcharge, canClipCharge, interconnection_limit); + percentGridcharge, canClipCharge, canCurtailCharge, interconnection_limit); batteryPower = dispatchManual->getBatteryPower(); batteryPower->connectionMode = ChargeController::AC_CONNECTED; @@ -74,7 +74,7 @@ TEST_F(ManualTest_lib_battery_dispatch, PowerLimitsDispatchManualDC) { powerDischargeMax, minimumModeTime, dispatchChoice, meterPosition, scheduleWeekday, scheduleWeekend, canCharge, canDischarge, canGridcharge, canDischargeToGrid, canGridcharge, percentDischarge, - percentGridcharge, canClipCharge, interconnection_limit); + percentGridcharge, canClipCharge, canCurtailCharge, interconnection_limit); batteryPower = dispatchManual->getBatteryPower(); batteryPower->connectionMode = ChargeController::DC_CONNECTED; @@ -103,7 +103,7 @@ TEST_F(ManualTest_lib_battery_dispatch, CurrentLimitsDispatchManualAC) { powerDischargeMax, minimumModeTime, dispatchChoice, meterPosition, scheduleWeekday, scheduleWeekend, canCharge, canDischarge, canGridcharge, canDischargeToGrid, canGridcharge, percentDischarge, - percentGridcharge, canClipCharge, interconnection_limit); + percentGridcharge, canClipCharge, canCurtailCharge, interconnection_limit); batteryPower = dispatchManual->getBatteryPower(); batteryPower->connectionMode = ChargeController::AC_CONNECTED; @@ -133,7 +133,7 @@ TEST_F(ManualTest_lib_battery_dispatch, CurrentLimitsDispatchManualDC) { powerDischargeMax, minimumModeTime, dispatchChoice, meterPosition, scheduleWeekday, scheduleWeekend, canCharge, canDischarge, canGridcharge, canDischargeToGrid, canGridcharge, percentDischarge, - percentGridcharge, canClipCharge, interconnection_limit); + percentGridcharge, canClipCharge, canCurtailCharge, interconnection_limit); batteryPower = dispatchManual->getBatteryPower(); batteryPower->connectionMode = ChargeController::DC_CONNECTED; @@ -166,7 +166,7 @@ TEST_F(ManualTest_lib_battery_dispatch, BothLimitsDispatchManualAC) { testDischargeMaxPower, minimumModeTime, dispatchChoice, meterPosition, scheduleWeekday, scheduleWeekend, canCharge, canDischarge, canGridcharge, canDischargeToGrid, canGridcharge, percentDischarge, - percentGridcharge, canClipCharge, interconnection_limit); + percentGridcharge, canClipCharge, canCurtailCharge, interconnection_limit); batteryPower = dispatchManual->getBatteryPower(); batteryPower->connectionMode = ChargeController::AC_CONNECTED; @@ -217,7 +217,7 @@ TEST_F(ManualTest_lib_battery_dispatch, BothLimitsDispatchManualDC) { powerDischargeMax, minimumModeTime, dispatchChoice, meterPosition, scheduleWeekday, scheduleWeekend, canCharge, canDischarge, canGridcharge, canDischargeToGrid, canGridcharge, percentDischarge, - percentGridcharge, canClipCharge, interconnection_limit); + percentGridcharge, canClipCharge, canCurtailCharge, interconnection_limit); batteryPower = dispatchManual->getBatteryPower(); batteryPower->connectionMode = ChargeController::DC_CONNECTED; @@ -267,7 +267,7 @@ TEST_F(ManualTest_lib_battery_dispatch, DispatchChangeFrequency) { powerDischargeMax, testMinTime, dispatchChoice, meterPosition, scheduleWeekday, scheduleWeekend, canCharge, canDischarge, canGridcharge, canDischargeToGrid, canGridcharge, percentDischarge, - percentGridcharge, canClipCharge, interconnection_limit); + percentGridcharge, canClipCharge, canCurtailCharge, interconnection_limit); batteryPower = dispatchManual->getBatteryPower(); batteryPower->connectionMode = ChargeController::AC_CONNECTED; @@ -314,7 +314,7 @@ TEST_F(ManualTest_lib_battery_dispatch, SOCLimitsOnDispatch) { powerDischargeMax, minimumModeTime, dispatchChoice, meterPosition, scheduleWeekday, scheduleWeekend, canCharge, canDischarge, canGridcharge, canDischargeToGrid, canGridcharge, percentDischarge, - percentGridcharge, canClipCharge, interconnection_limit); + percentGridcharge, canClipCharge, canCurtailCharge, interconnection_limit); batteryPower = dispatchManual->getBatteryPower(); batteryPower->connectionMode = ChargeController::AC_CONNECTED; @@ -373,7 +373,7 @@ TEST_F(ManualTest_lib_battery_dispatch, ManualGridChargingOffTest) powerDischargeMax, minimumModeTime, dispatchChoice, meterPosition, scheduleWeekday, scheduleWeekend, canCharge, canDischarge, canGridcharge, canDischargeToGrid, canGridcharge, percentDischarge, - percentGridcharge, canClipCharge, interconnection_limit); + percentGridcharge, canClipCharge, canCurtailCharge, interconnection_limit); batteryPower = dispatchManual->getBatteryPower(); batteryPower->connectionMode = ChargeController::DC_CONNECTED; @@ -399,7 +399,7 @@ TEST_F(ManualTest_lib_battery_dispatch, ManualGridChargingOnTest) powerDischargeMax, minimumModeTime, dispatchChoice, meterPosition, scheduleWeekday, scheduleWeekend, canCharge, canDischarge, testCanGridcharge, canDischargeToGrid, canGridcharge, percentDischarge, - testPercentGridCharge, canClipCharge, interconnection_limit); + testPercentGridCharge, canClipCharge, canCurtailCharge, interconnection_limit); batteryPower = dispatchManual->getBatteryPower(); batteryPower->connectionMode = ChargeController::AC_CONNECTED; @@ -425,7 +425,7 @@ TEST_F(ManualTest_lib_battery_dispatch, ManualGridChargingOnDCConnectedTest) powerDischargeMax, minimumModeTime, dispatchChoice, meterPosition, scheduleWeekday, scheduleWeekend, canCharge, canDischarge, testCanGridcharge, canDischargeToGrid, canGridcharge, percentDischarge, - testPercentGridCharge, canClipCharge, interconnection_limit); + testPercentGridCharge, canClipCharge, canCurtailCharge, interconnection_limit); batteryPower = dispatchManual->getBatteryPower(); batteryPower->connectionMode = ChargeController::DC_CONNECTED; @@ -452,7 +452,7 @@ TEST_F(ManualTest_lib_battery_dispatch, NoGridChargingWhilePVIsOnTest) powerDischargeMax, minimumModeTime, dispatchChoice, meterPosition, scheduleWeekday, scheduleWeekend, canCharge, canDischarge, testCanGridcharge, canDischargeToGrid, canGridcharge, percentDischarge, - testPercentGridCharge, canClipCharge, interconnection_limit); + testPercentGridCharge, canClipCharge, canCurtailCharge, interconnection_limit); batteryPower = dispatchManual->getBatteryPower(); batteryPower->connectionMode = ChargeController::AC_CONNECTED; @@ -471,7 +471,7 @@ TEST_F(ManualTest_lib_battery_dispatch, EfficiencyLimitsDispatchManualDC) powerDischargeMax, minimumModeTime, dispatchChoice, meterPosition, scheduleWeekday, scheduleWeekend, canCharge, canDischarge, canGridcharge, canDischargeToGrid, canGridcharge, percentDischarge, - percentGridcharge, canClipCharge, interconnection_limit); + percentGridcharge, canClipCharge, canCurtailCharge, interconnection_limit); batteryPower = dispatchManual->getBatteryPower(); batteryPower->connectionMode = ChargeController::DC_CONNECTED; @@ -502,7 +502,7 @@ TEST_F(ManualTest_lib_battery_dispatch, InverterEfficiencyCutoffDC) currentDischargeMax, powerChargeMax, powerDischargeMax, powerChargeMax, powerDischargeMax, minimumModeTime, dispatchChoice, meterPosition, scheduleWeekday, scheduleWeekend, canCharge, - canDischarge, testCanGridcharge, canDischargeToGrid, canGridcharge, testPercentGridCharge, testPercentGridCharge, canClipCharge, interconnection_limit); + canDischarge, testCanGridcharge, canDischargeToGrid, canGridcharge, testPercentGridCharge, testPercentGridCharge, canClipCharge, canCurtailCharge, interconnection_limit); batteryPower = dispatchManual->getBatteryPower(); batteryPower->connectionMode = ChargeController::DC_CONNECTED; @@ -545,7 +545,7 @@ TEST_F(ManualTest_lib_battery_dispatch_losses, TestLossesWithDispatch) powerDischargeMax, minimumModeTime, dispatchChoice, meterPosition, scheduleWeekday, scheduleWeekend, canCharge, canDischarge, canGridcharge, canDischargeToGrid, canGridcharge, percentDischarge, - percentGridcharge, canClipCharge, interconnection_limit); + percentGridcharge, canClipCharge, canCurtailCharge, interconnection_limit); batteryPower = dispatchManual->getBatteryPower(); batteryPower->connectionMode = ChargeController::DC_CONNECTED; @@ -574,7 +574,7 @@ TEST_F(ManualTest_lib_battery_dispatch, TestDischargeToGrid) powerDischargeMax, minimumModeTime, dispatchChoice, meterPosition, scheduleWeekday, scheduleWeekend, canCharge, canDischarge, canGridcharge, canGridcharge, testCanDischargeToGrid, percentDischarge, - percentGridcharge, canClipCharge, interconnection_limit); + percentGridcharge, canClipCharge, canCurtailCharge, interconnection_limit); batteryPower = dispatchManual->getBatteryPower(); batteryPower->connectionMode = ChargeController::AC_CONNECTED; @@ -600,7 +600,7 @@ TEST_F(ManualTest_lib_battery_dispatch, TestClipCharging) powerDischargeMax, minimumModeTime, dispatchChoice, meterPosition, scheduleWeekday, scheduleWeekend, testDoNothingExceptClipCharge, testDoNothingExceptClipCharge, testDoNothingExceptClipCharge, testDoNothingExceptClipCharge, testDoNothingExceptClipCharge, percentDischarge, - percentGridcharge, canClipCharge, interconnection_limit); + percentGridcharge, canClipCharge, canCurtailCharge, interconnection_limit); batteryPower = dispatchManual->getBatteryPower(); batteryPower->connectionMode = ChargeController::DC_CONNECTED; @@ -622,7 +622,7 @@ TEST_F(ManualTest_lib_battery_dispatch, OutageWithManualDispatch) { powerDischargeMax, minimumModeTime, dispatchChoice, meterPosition, scheduleWeekday, scheduleWeekend, canCharge, canDischarge, canGridcharge, canGridcharge, canGridcharge, percentDischarge, - percentGridcharge, canClipCharge, interconnection_limit); + percentGridcharge, canClipCharge, canCurtailCharge, interconnection_limit); batteryPower = dispatchManual->getBatteryPower(); batteryPower->connectionMode = ChargeController::AC_CONNECTED; @@ -695,7 +695,7 @@ TEST_F(ManualTest_lib_battery_dispatch, PVPriorityLoadFirst) powerDischargeMax, minimumModeTime, dispatchChoice, meterPosition, scheduleWeekday, scheduleWeekend, canCharge, canDischarge, canGridcharge, canDischargeToGrid, canGridcharge, percentDischarge, - percentGridcharge, canClipCharge, interconnection_limit, + percentGridcharge, canClipCharge, canCurtailCharge, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, SOC_min_outage, priorityChargeBattery); batteryPower = dispatchManual->getBatteryPower(); @@ -722,7 +722,7 @@ TEST_F(ManualTest_lib_battery_dispatch, PVPriorityBatteryFirst) powerDischargeMax, minimumModeTime, dispatchChoice, meterPosition, scheduleWeekday, scheduleWeekend, canCharge, canDischarge, canGridcharge, canDischargeToGrid, canGridcharge, percentDischarge, - percentGridcharge, canClipCharge, interconnection_limit, + percentGridcharge, canClipCharge, canCurtailCharge, interconnection_limit, chargeOnlySystemExceedLoad, dischargeOnlyLoadExceedSystem, SOC_min_outage, priorityChargeBattery); batteryPower = dispatchManual->getBatteryPower(); @@ -737,3 +737,52 @@ TEST_F(ManualTest_lib_battery_dispatch, PVPriorityBatteryFirst) EXPECT_NEAR(batteryPower->powerGridToLoad, 50.0, 1.0); } + +TEST_F(ManualTest_lib_battery_dispatch, ManualInterconnectionLimitTest) +{ + interconnection_limit = 500; + canCurtailCharge = true; + // canGridCharge is false by default + dispatchManual = new dispatch_manual_t(batteryModel, dtHour, SOC_min, SOC_max, currentChoice, currentChargeMax, + currentDischargeMax, powerChargeMax, powerDischargeMax, powerChargeMax, + powerDischargeMax, minimumModeTime, + dispatchChoice, meterPosition, scheduleWeekday, scheduleWeekend, canCharge, + canDischarge, canGridcharge, canDischargeToGrid, canGridcharge, percentDischarge, + percentGridcharge, canClipCharge, canCurtailCharge, interconnection_limit); + + batteryPower = dispatchManual->getBatteryPower(); + batteryPower->connectionMode = ChargeController::DC_CONNECTED; + batteryPower->setSharedInverter(m_sharedInverter); + + // Should charge since PV is being curtailed + batteryPower->powerSystem = 600; batteryPower->voltageSystem = 600; batteryPower->powerGridToBattery = 0; + dispatchManual->dispatch(year, hour_of_year, step_of_hour); + EXPECT_NEAR(batteryPower->powerBatteryDC, -47.9, 0.1); + EXPECT_NEAR(batteryPower->powerSystemToBatteryDC, 48.4, 0.1); +} + +TEST_F(ManualTest_lib_battery_dispatch, TestDischargeToGridInterconnectionLimit) +{ + interconnection_limit = 10; + std::vector testCanDischargeToGrid; + for (int p = 0; p < 6; p++) { + testCanDischargeToGrid.push_back(1); + } + dispatchManual = new dispatch_manual_t(batteryModel, dtHour, SOC_min, SOC_max, currentChoice, currentChargeMax, + currentDischargeMax, powerChargeMax, powerDischargeMax, powerChargeMax, + powerDischargeMax, minimumModeTime, + dispatchChoice, meterPosition, scheduleWeekday, scheduleWeekend, canCharge, + canDischarge, canGridcharge, canGridcharge, testCanDischargeToGrid, percentDischarge, + percentGridcharge, canClipCharge, canCurtailCharge, interconnection_limit); + + batteryPower = dispatchManual->getBatteryPower(); + batteryPower->connectionMode = ChargeController::AC_CONNECTED; + batteryPower->inverterEfficiencyCutoff = 0; + + // Test discharge to grid - should only charge at interconnection limit + batteryPower->powerSystem = 0; batteryPower->powerLoad = 30; batteryPower->voltageSystem = 600; batteryPower->powerBatteryDC = 1000; + dispatchManual->dispatch(year, hour_of_year, step_of_hour); + EXPECT_NEAR(batteryPower->powerBatteryDC, 41.66, 1.0); + EXPECT_NEAR(batteryPower->powerBatteryToLoad, batteryPower->powerLoad, 2.0); + EXPECT_NEAR(batteryPower->powerBatteryToGrid, 10, 0.1); +} diff --git a/test/shared_test/lib_battery_dispatch_test.h b/test/shared_test/lib_battery_dispatch_test.h index 60cd7d682..e9bf22deb 100644 --- a/test/shared_test/lib_battery_dispatch_test.h +++ b/test/shared_test/lib_battery_dispatch_test.h @@ -72,6 +72,7 @@ struct DispatchProperties { std::map percentDischarge; std::map percentGridcharge; bool canClipCharge = false; + bool canCurtailCharge = false; // resource std::vector pv;