diff --git a/shared/lib_battery_voltage.cpp b/shared/lib_battery_voltage.cpp index ce344e928..fd42afed4 100644 --- a/shared/lib_battery_voltage.cpp +++ b/shared/lib_battery_voltage.cpp @@ -256,9 +256,9 @@ double voltage_table_t::calculate_current_for_target_w(double P_watts, double q, P_watts /= params->num_cells_series; P_watts *= params->dt_hr; - double multiplier = 1.; + int multiplier = 1; if (P_watts < 0) - multiplier = -1.; + multiplier = -1; size_t row = 0; while (row < params->voltage_table.size() && DOD > params->voltage_table[row][0]) { @@ -269,12 +269,12 @@ double voltage_table_t::calculate_current_for_target_w(double P_watts, double q, double B = qmax / 100.; double DOD_new = 0.; - double incr = 0; - double DOD_best = DOD_best = multiplier == -1. ? 0 : 100; + int incr = 0; + double DOD_best = DOD_best = (multiplier == -1) ? 0 : 100; double P_best = 0; - while (incr + row < slopes.size() && incr + row >= 0) { - size_t i = row + (size_t) incr; - incr += 1 * multiplier; + while (((incr + row) < slopes.size()) && ((incr + row) >= 0)) { + size_t i = row + incr; + incr += multiplier; double a = B * slopes[i]; double b = A * slopes[i] + B * intercepts[i]; diff --git a/test/main.cpp b/test/main.cpp index 5e1bcc04b..08c4d3809 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -54,6 +54,7 @@ GTEST_API_ int main(int argc, char **argv) { // filter to include // ::testing::GTEST_FLAG(filter) = "CmodPVWatts*:CMPvwatts*"; + //::testing::GTEST_FLAG(filter) = "CMBatteryStatefulIntegration_cmod_battery_stateful.ssc_1023"; // filter to exclude // ::testing::GTEST_FLAG(filter) = "-PVSmoothing_lib_battery_dispatch*"; diff --git a/test/ssc_test/cmod_battery_stateful_test.cpp b/test/ssc_test/cmod_battery_stateful_test.cpp index 10ee68c5d..9048a44cb 100644 --- a/test/ssc_test/cmod_battery_stateful_test.cpp +++ b/test/ssc_test/cmod_battery_stateful_test.cpp @@ -436,4 +436,29 @@ TEST_F(CMBatteryStatefulIntegration_cmod_battery_stateful, TestReplacementByCapa EXPECT_EQ(vt->as_integer("n_replacements"), 1); EXPECT_EQ(vt->as_vector_ssc_number_t("indices_replaced")[1], 2); EXPECT_EQ(vt->as_number("q_relative"), 100); -} \ No newline at end of file +} + + + +TEST_F(CMBatteryStatefulIntegration_cmod_battery_stateful, ssc_1023) { + double dt_hour = 1.0 / 60; + ssc_number_t power, soc, current, temp; + + CreateLMOLTOssc1023Model(dt_hour); + + for (size_t i = 0; i < 50; i++) { + ssc_data_set_number(data, "input_power", -0.1); + ssc_module_exec(mod, data); + ssc_data_get_number(data, "P", &power); + ssc_data_get_number(data, "SOC", &soc); + ssc_data_get_number(data, "I", ¤t); + ssc_data_get_number(data, "T_batt", &temp); + // uncomment following to check all iterations + //std::cout << i << ": Power=" << power << ", SOC=" << soc << ", I=" << current << ", T_Batt=" << temp << "\n"; + } + EXPECT_NEAR(power, -0.1, 1e-4); + EXPECT_NEAR(soc, 20.8265, 1e-4); + EXPECT_NEAR(current, -0.495549, 1e-6); + EXPECT_NEAR(temp, 20, 1e-4); +} + diff --git a/test/ssc_test/cmod_battery_stateful_test.h b/test/ssc_test/cmod_battery_stateful_test.h index 311f6ff8d..d0d779eaa 100644 --- a/test/ssc_test/cmod_battery_stateful_test.h +++ b/test/ssc_test/cmod_battery_stateful_test.h @@ -88,6 +88,29 @@ class CMBatteryStatefulIntegration_cmod_battery_stateful : public ::testing::Tes EXPECT_TRUE(ssc_stateful_module_setup(mod, data)); } + void CreateLMOLTOssc1023Model(double dt_hour = 1.) + { // from nrel-PySAM 4.1.0 + /* + import PySAM.BatteryStateful as battery + + b = battery.default('LMOLTO') + */ + params_str = R"({"Qfull": 2.0, "Vnom_default": 2.4, "calendar_choice": 0.0, "chem": 1.0, "cycling_matrix": [ [20.0, 0.0, 100.0], [20.0, 10000.0, 90.0], [20.0, 20000.0, 85.42], [20.0, 30000.0, 83.33], [80.0, 0.0, 100.0], [80.0, 2000.0, 90.0], [80.0, 4000.0, 85.42], [80.0, 6000.0, 83.33]], "life_model": 2.0, "resistance": 0.001, "voltage_choice": 1.0, "voltage_matrix": [[0.0, 2.66443299], [3.538710415, 2.63900522], [10.42095268, 2.612970471], [17.30319495, 2.593547721], [24.18543722, 2.576117428], [31.06767949, 2.558760928], [37.94992175, 2.540459858], [44.83216402, 2.520372957], [51.71440629, 2.498618297], [58.59664856, 2.476125691], [65.47889082, 2.452821343], [72.36113309, 2.427554059], [79.24337536, 2.402080149], [86.12561763, 2.374171016], [93.00785989, 2.334867991], [97.39981713, 2.245030365], [98.58997933, 2.038415189], [98.6723647, 1.784428794], [99.07509979, 1.614765137], [100.0, 1.1]], "Cp": 900.0, "T_room_init": 20, "cap_vs_temp": [[-20.0, 72.33333333], [-10.0, 81.8], [0.0, 88.8], [10.0, 93.0], [23.0, 96.66666667], [45.0, 101.0], [60.0, 101.0]], "h": 7.5, "mass": 500.000, "nominal_energy": 10.0, "nominal_voltage": 200.0, "surface_area": 6.3 })"; + + data = json_to_ssc_data(params_str.c_str()); + ssc_data_set_number(data, "dt_hr", dt_hour); + + // python script additional inputs for setup to work + ssc_data_set_number(data, "control_mode", 1); + ssc_data_set_number(data, "initial_SOC", 20); + ssc_data_set_number(data, "minimum_SOC", 20); + ssc_data_set_number(data, "maximum_SOC", 90); + ssc_data_set_number(data, "input_power", 0); + + mod = ssc_module_create("battery_stateful"); + EXPECT_TRUE(ssc_stateful_module_setup(mod, data)); + } + void TearDown() override { ssc_data_free(data); ssc_module_free(mod);