Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ssc 1058 ac loss accounting #1061

Merged
merged 4 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 30 additions & 19 deletions shared/lib_battery_powerflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,11 @@ void BatteryPowerFlow::calculateACConnected()

// Code simplification to remove redundancy for code that should use either critical load or actual load
double calc_load_ac = (m_BatteryPower->isOutageStep ? P_crit_load_ac : P_load_ac);
double P_required_for_load = calc_load_ac;

if (ac_loss_percent_post_battery < 1) { // Account for possible divide by zero
P_required_for_load /= (1 - ac_loss_percent_post_battery);
}

// charging and idle
if (P_battery_ac <= 0)
Expand All @@ -365,11 +370,11 @@ void BatteryPowerFlow::calculateACConnected()
if (m_BatteryPower->chargeOnlySystemExceedLoad) {
P_pv_to_load_ac = P_pv_ac;

if (P_pv_to_load_ac > calc_load_ac) {
P_pv_to_load_ac = calc_load_ac;
if (P_pv_to_load_ac > P_required_for_load) {
P_pv_to_load_ac = P_required_for_load;
}
// Fuel cell goes to load next
P_fuelcell_to_load_ac = std::fmin(calc_load_ac - P_pv_to_load_ac, P_fuelcell_ac);
P_fuelcell_to_load_ac = std::fmin(P_required_for_load - P_pv_to_load_ac, P_fuelcell_ac);
}

// Excess PV can go to battery, if PV can cover charging losses
Expand Down Expand Up @@ -398,11 +403,11 @@ void BatteryPowerFlow::calculateACConnected()
P_pv_to_load_ac = P_pv_ac - P_pv_to_batt_ac;
}

if (P_pv_to_load_ac > calc_load_ac) {
P_pv_to_load_ac = calc_load_ac;
if (P_pv_to_load_ac > P_required_for_load) {
P_pv_to_load_ac = P_required_for_load;
}
// Fuel cell goes to load next
P_fuelcell_to_load_ac = std::fmin(calc_load_ac - P_pv_to_load_ac, P_fuelcell_ac);
P_fuelcell_to_load_ac = std::fmin(P_required_for_load - P_pv_to_load_ac, P_fuelcell_ac);
}

// Fuelcell can also charge battery
Expand Down Expand Up @@ -439,6 +444,7 @@ void BatteryPowerFlow::calculateACConnected()
// discharging, not idle
else
{

// Test if battery is discharging erroneously
if (!m_BatteryPower->canDischarge && P_battery_ac > 0) {
P_batt_to_grid_ac = P_batt_to_load_ac = 0;
Expand All @@ -448,9 +454,9 @@ void BatteryPowerFlow::calculateACConnected()
P_pv_to_load_ac = P_pv_ac;

// Excess PV production, no other component meets load
if (P_pv_ac >= calc_load_ac)
if (P_pv_ac >= P_required_for_load)
{
P_pv_to_load_ac = calc_load_ac;
P_pv_to_load_ac = P_required_for_load;
P_fuelcell_to_load_ac = 0;
P_batt_to_load_ac = 0;

Expand All @@ -459,14 +465,14 @@ void BatteryPowerFlow::calculateACConnected()
P_fuelcell_to_grid_ac = P_fuelcell_ac;
}
else {
P_fuelcell_to_load_ac = std::fmin(P_fuelcell_ac, calc_load_ac - P_pv_to_load_ac);
P_batt_to_load_ac = std::fmin(P_battery_ac - P_system_loss_ac, calc_load_ac - P_pv_to_load_ac - P_fuelcell_to_load_ac);
P_fuelcell_to_load_ac = std::fmin(P_fuelcell_ac, P_required_for_load - P_pv_to_load_ac);
P_batt_to_load_ac = std::fmin(P_battery_ac - P_system_loss_ac, P_required_for_load - P_pv_to_load_ac - P_fuelcell_to_load_ac);
}
}
else {
P_batt_to_load_ac = std::fmin(P_battery_ac, calc_load_ac);
P_fuelcell_to_load_ac = std::fmin(P_fuelcell_ac, calc_load_ac - P_batt_to_load_ac);
P_pv_to_load_ac = std::fmin(std::fmax(0, calc_load_ac - P_fuelcell_to_load_ac - P_batt_to_load_ac), P_pv_ac);
P_batt_to_load_ac = std::fmin(P_battery_ac, P_required_for_load);
P_fuelcell_to_load_ac = std::fmin(P_fuelcell_ac, P_required_for_load - P_batt_to_load_ac);
P_pv_to_load_ac = std::fmin(std::fmax(0, P_required_for_load - P_fuelcell_to_load_ac - P_batt_to_load_ac), P_pv_ac);
P_pv_to_grid_ac = std::fmax(0, P_pv_ac - P_pv_to_load_ac);
P_fuelcell_to_grid_ac = std::fmax(0, P_fuelcell_ac - P_fuelcell_to_load_ac);
}
Expand All @@ -483,11 +489,8 @@ void BatteryPowerFlow::calculateACConnected()
P_fuelcell_to_grid_ac = 0;
}

// Priliminary batt to grid for DC losses
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks like a conjunction of prilliman and preliminary

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, fixed.

P_batt_to_grid_ac = P_battery_ac - P_system_loss_ac - P_batt_to_load_ac - P_batt_to_pv_inverter;
if (m_BatteryPower->isOutageStep && P_batt_to_grid_ac > tolerance) {
m_BatteryPower->powerBatteryDC = (P_battery_ac - P_batt_to_grid_ac) / m_BatteryPower->singlePointEfficiencyDCToAC;
return calculateACConnected();
}

P_fuelcell_to_grid_ac = P_fuelcell_ac - P_fuelcell_to_load_ac;
P_batt_to_system_loss = P_system_loss_ac;
Expand All @@ -503,15 +506,23 @@ void BatteryPowerFlow::calculateACConnected()
// Compute total system output and grid power flow
P_gen_ac = P_pv_ac + P_fuelcell_ac + P_inverter_draw_ac + P_battery_ac - P_system_loss_ac;

// Final batt to grid for outage accounting
if (P_battery_ac > 0)
{
P_batt_to_grid_ac = P_battery_ac * (1 - ac_loss_percent_post_battery) - P_system_loss_ac - P_batt_to_load_ac - P_batt_to_pv_inverter;
if (m_BatteryPower->isOutageStep && P_batt_to_grid_ac > tolerance) {
m_BatteryPower->powerBatteryDC = (P_battery_ac - P_batt_to_grid_ac) / m_BatteryPower->singlePointEfficiencyDCToAC;
return calculateACConnected();
}
}

// Apply AC losses to powerflow - note that these are applied to gen later
P_pv_to_batt_ac *= (1 - ac_loss_percent_post_battery);
P_pv_to_load_ac *= (1 - ac_loss_percent_post_battery);
P_pv_to_batt_ac *= (1 - ac_loss_percent_post_battery);
P_pv_to_grid_ac *= (1 - ac_loss_percent_post_battery);
P_grid_to_batt_ac *= (1 - ac_loss_percent_post_battery);
P_grid_to_load_ac *= (1 - ac_loss_percent_post_battery);
P_batt_to_load_ac *= (1 - ac_loss_percent_post_battery);
P_batt_to_grid_ac *= (1 - ac_loss_percent_post_battery);
P_fuelcell_to_batt_ac *= (1 - ac_loss_percent_post_battery);
P_fuelcell_to_load_ac *= (1 - ac_loss_percent_post_battery);
P_fuelcell_to_grid_ac *= (1 - ac_loss_percent_post_battery);
Expand Down
84 changes: 84 additions & 0 deletions test/shared_test/lib_battery_powerflow_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3055,6 +3055,47 @@ TEST_F(BatteryPowerFlowTest_lib_battery_powerflow, AC_system_w_ac_losses) {
gen = m_batteryPower->powerSystem + m_batteryPower->powerBatteryAC;
EXPECT_NEAR(m_batteryPower->powerGeneratedBySystem, gen, error);
EXPECT_NEAR(m_batteryPower->powerLoad, 0, error);

// Post batt loss affects meeting critical load
m_batteryPower->acLossPostBattery = 0.05;
m_batteryPower->acLossWiring = 0;
m_batteryPower->powerBatteryDC = 50;
m_batteryPower->isOutageStep = true;
m_batteryPower->powerCritLoad = 50;
m_batteryPower->powerLoad = 50;
m_batteryPowerFlow->calculate();

EXPECT_NEAR(m_batteryPower->powerBatteryAC, 48, error);
EXPECT_NEAR(m_batteryPower->powerSystemToLoad, 0, error);
EXPECT_NEAR(m_batteryPower->powerSystemToBatteryAC, 0, error);
EXPECT_NEAR(m_batteryPower->powerGridToBattery, 0, error);
EXPECT_NEAR(m_batteryPower->powerBatteryToLoad, 45.6, error);
EXPECT_NEAR(m_batteryPower->powerCritLoadUnmet, 4.4, error);
EXPECT_NEAR(m_batteryPower->powerSystemToGrid, 0, error);
EXPECT_NEAR(m_batteryPower->powerConversionLoss, 2, error);
EXPECT_NEAR(m_batteryPower->powerSystemLoss, 0.0, error);
EXPECT_NEAR(m_batteryPower->powerLoad, 50, error);

// Increasing batt power allows meeting critical load
m_batteryPower->acLossPostBattery = 0.05;
m_batteryPower->acLossWiring = 0;
m_batteryPower->powerBatteryDC = 60;
m_batteryPower->isOutageStep = true;
m_batteryPower->powerLoad = 50;
m_batteryPower->powerCritLoad = 50;
m_batteryPowerFlow->calculate();

EXPECT_NEAR(m_batteryPower->powerBatteryAC, 55.4, error);
EXPECT_NEAR(m_batteryPower->powerBatteryDC, 57.7, error);
EXPECT_NEAR(m_batteryPower->powerSystemToLoad, 0, error);
EXPECT_NEAR(m_batteryPower->powerSystemToBatteryAC, 0, error);
EXPECT_NEAR(m_batteryPower->powerGridToBattery, 0, error);
EXPECT_NEAR(m_batteryPower->powerBatteryToLoad, 50.0, error);
EXPECT_NEAR(m_batteryPower->powerCritLoadUnmet, 0.0, error);
EXPECT_NEAR(m_batteryPower->powerSystemToGrid, 0, error);
EXPECT_NEAR(m_batteryPower->powerConversionLoss, 2.308, error);
EXPECT_NEAR(m_batteryPower->powerSystemLoss, 0.0, error);
EXPECT_NEAR(m_batteryPower->powerLoad, 50, error);
}

TEST_F(BatteryPowerFlowTest_lib_battery_powerflow, DC_system_w_ac_losses) {
Expand Down Expand Up @@ -3259,4 +3300,47 @@ TEST_F(BatteryPowerFlowTest_lib_battery_powerflow, DC_system_w_ac_losses) {
EXPECT_NEAR(m_batteryPower->powerConversionLoss, 3.738, error);
EXPECT_NEAR(m_batteryPower->powerSystemLoss, 0.0, error);
EXPECT_NEAR(m_batteryPower->powerLoad, 0, error);

m_batteryPower->acXfmrLoadLoss = 0.0;
m_batteryPower->acXfmrNoLoadLoss = 0.0;

// Post batt loss affects meeting critical load
m_batteryPower->acLossPostBattery = 0.05;
m_batteryPower->acLossWiring = 0;
m_batteryPower->powerBatteryDC = 50;
m_batteryPower->isOutageStep = true;
m_batteryPower->powerCritLoad = 50;
m_batteryPower->powerLoad = 50;
m_batteryPowerFlow->calculate();

EXPECT_NEAR(m_batteryPower->powerBatteryAC, 46.26, error);
EXPECT_NEAR(m_batteryPower->powerSystemToLoad, 0, error);
EXPECT_NEAR(m_batteryPower->powerSystemToBatteryAC, 0, error);
EXPECT_NEAR(m_batteryPower->powerGridToBattery, 0, error);
EXPECT_NEAR(m_batteryPower->powerBatteryToLoad, 43.947, error);
EXPECT_NEAR(m_batteryPower->powerCritLoadUnmet, 6.053, error);
EXPECT_NEAR(m_batteryPower->powerSystemToGrid, 0, error);
EXPECT_NEAR(m_batteryPower->powerConversionLoss, 3.738, error);
EXPECT_NEAR(m_batteryPower->powerSystemLoss, 0.0, error);
EXPECT_NEAR(m_batteryPower->powerLoad, 50, error);

// Increasing batt power allows meeting critical load
m_batteryPower->acLossPostBattery = 0.05;
m_batteryPower->acLossWiring = 0;
m_batteryPower->powerBatteryDC = 60;
m_batteryPower->isOutageStep = true;
m_batteryPower->powerLoad = 50;
m_batteryPower->powerCritLoad = 50;
m_batteryPowerFlow->calculate();

EXPECT_NEAR(m_batteryPower->powerBatteryAC, 52.63, error);
EXPECT_NEAR(m_batteryPower->powerSystemToLoad, 0, error);
EXPECT_NEAR(m_batteryPower->powerSystemToBatteryAC, 0, error);
EXPECT_NEAR(m_batteryPower->powerGridToBattery, 0, error);
EXPECT_NEAR(m_batteryPower->powerBatteryToLoad, 50.0, error);
EXPECT_NEAR(m_batteryPower->powerCritLoadUnmet, 0.0, error);
EXPECT_NEAR(m_batteryPower->powerSystemToGrid, 0, error);
EXPECT_NEAR(m_batteryPower->powerConversionLoss, 3.99, error);
EXPECT_NEAR(m_batteryPower->powerSystemLoss, 0.0, error);
EXPECT_NEAR(m_batteryPower->powerLoad, 50, error);
}