Skip to content

Commit

Permalink
Merge branch 'develop' into SAM_1903
Browse files Browse the repository at this point in the history
  • Loading branch information
sjanzou committed Nov 15, 2024
2 parents a95a943 + ff30186 commit b241d0e
Show file tree
Hide file tree
Showing 39 changed files with 1,018 additions and 543 deletions.
11 changes: 3 additions & 8 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,11 @@ if(APPLE)
set(CMAKE_OSX_DEPLOYMENT_TARGET "12" CACHE STRING "Minimum OS X deployment version")
endif()

if (UNIX AND NOT CMAKE_C_COMPILER)
set(CMAKE_C_COMPILER gcc)
set(CMAKE_CXX_COMPILER g++)
endif()
set(CMAKE_CXX_STANDARD 11)

if ( NOT APPLE)
set(CURL_DIR build_resources/libcurl_ssl_x64)
endif()

Project(sam_simulation_core VERSION 1.0.0)
Project(sam_simulation_core VERSION 1.0.0 LANGUAGES CXX C)


#####################################################################################################################
Expand Down Expand Up @@ -82,14 +76,15 @@ function(set_default_compile_options target)
set(MAIN_CFLAGS "")
endif()
set(MAIN_CFLAGS "${MAIN_CFLAGS} -D__64BIT__")
set_property(TARGET ${target} PROPERTY CXX_STANDARD 11)
set_property(TARGET ${target} PROPERTY CXX_STANDARD_REQUIRED ON)
if(MSVC)
set(MAIN_CFLAGS "${MAIN_CFLAGS} /bigobj /MP")
set(MAIN_CFLAGS "${MAIN_CFLAGS} /D__WINDOWS__ /D_WINDOWS /D_CRT_SECURE_NO_WARNINGS /DLPWINAPP")
foreach (flag_var CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG)
set(${flag_var} "${${flag_var}} /D_DEBUG" CACHE STRING "compile flags" FORCE)
endforeach()
else(MSVC)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
if (APPLE)
set(MAIN_CFLAGS "${MAIN_CFLAGS} -fno-common -DWX_PRECOMP -D__MACOSX__")
else()
Expand Down
8 changes: 6 additions & 2 deletions sdktool/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,15 @@ endif()
target_link_libraries(SDKtool ${wxWidgets_LIBRARIES})

if (UNIX AND NOT APPLE)
target_link_libraries(SDKtool -ldl -lfontconfig)
target_link_libraries(SDKtool ${CMAKE_DL_LIBS} -lfontconfig)
endif()

if (UNIX)
target_link_libraries(SDKtool -lm -lcurl)
find_library(MATH_LIBRARY m)
if(MATH_LIBRARY)
target_link_libraries(SDKtool ${MATH_LIBRARY})
endif()
target_link_libraries(SDKtool -lcurl)
elseif (MSVC)
find_library( CURL_LIB
NAMES libcurl.lib
Expand Down
38 changes: 26 additions & 12 deletions shared/lib_battery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ Define Losses
*/
void losses_t::initialize() {
state = std::make_shared<losses_state>();
state->loss_kw = 0;
state->ancillary_loss_kw = 0;
if (params->loss_choice == losses_params::MONTHLY) {
if (params->monthly_charge_loss.size() == 1) {
params->monthly_charge_loss = std::vector<double>(12, params->monthly_charge_loss[0]);
Expand Down Expand Up @@ -210,19 +210,21 @@ void losses_t::initialize() {
}
}

losses_t::losses_t(const std::vector<double>& monthly_charge, const std::vector<double>& monthly_discharge, const std::vector<double>& monthly_idle) {
losses_t::losses_t(const std::vector<double>& monthly_charge, const std::vector<double>& monthly_discharge, const std::vector<double>& monthly_idle, const std::vector<double>& adjust_losses) {
params = std::make_shared<losses_params>();
params->loss_choice = losses_params::MONTHLY;
params->monthly_charge_loss = monthly_charge;
params->monthly_discharge_loss = monthly_discharge;
params->monthly_idle_loss = monthly_idle;
params->adjust_loss = adjust_losses;
initialize();
}

losses_t::losses_t(const std::vector<double>& schedule_loss) {
losses_t::losses_t(const std::vector<double>& schedule_loss, const std::vector<double>& adjust_losses) {
params = std::make_shared<losses_params>();
params->loss_choice = losses_params::SCHEDULE;
params->schedule_loss = schedule_loss;
params->adjust_loss = adjust_losses;
initialize();
}

Expand Down Expand Up @@ -252,18 +254,24 @@ void losses_t::run_losses(size_t lifetimeIndex, double dtHour, double charge_ope
// update system losses depending on user input
if (params->loss_choice == losses_params::MONTHLY) {
if (charge_operation == capacity_state::CHARGE)
state->loss_kw = params->monthly_charge_loss[monthIndex];
state->ancillary_loss_kw = params->monthly_charge_loss[monthIndex];
if (charge_operation == capacity_state::DISCHARGE)
state->loss_kw = params->monthly_discharge_loss[monthIndex];
state->ancillary_loss_kw = params->monthly_discharge_loss[monthIndex];
if (charge_operation == capacity_state::NO_CHARGE)
state->loss_kw = params->monthly_idle_loss[monthIndex];
state->ancillary_loss_kw = params->monthly_idle_loss[monthIndex];
}
else if (params->loss_choice == losses_params::SCHEDULE) {
state->loss_kw = params->schedule_loss[lifetimeIndex % params->schedule_loss.size()];
state->ancillary_loss_kw = params->schedule_loss[lifetimeIndex % params->schedule_loss.size()];
}

state->adjust_loss_percent = getAvailabilityLoss(lifetimeIndex);
}

double losses_t::getLoss() { return state->loss_kw; }
double losses_t::getAncillaryLoss() { return state->ancillary_loss_kw; }

double losses_t::getAvailabilityLoss(size_t lifetimeIndex) {
return params->adjust_loss[lifetimeIndex % params->adjust_loss.size()];
}

losses_state losses_t::get_state() { return *state; }

Expand Down Expand Up @@ -584,7 +592,7 @@ double battery_t::run(size_t lifetimeIndex, double &I) {

while (iterate_count < 5) {
runThermalModel(I, lifetimeIndex);
runCapacityModel(I);
runCapacityModel(I, lifetimeIndex);

double numerator = std::abs(I - I_initial);
if ((numerator > 0.0) && (numerator / std::abs(I_initial) > tolerance)) {
Expand Down Expand Up @@ -622,12 +630,14 @@ double battery_t::estimateCycleDamage() {
return lifetime->estimateCycleDamage();
}

void battery_t::runCapacityModel(double &I) {
void battery_t::runCapacityModel(double &I, size_t lifetimeIndex) {
// Don't update max capacity if the battery is idle
if (std::abs(I) > tolerance) {
// Need to first update capacity model to ensure temperature accounted for
capacity->updateCapacityForThermal(thermal->capacity_percent());
}
double availability_loss = losses->getAvailabilityLoss(lifetimeIndex);
capacity->updateCapacityForAvailability(availability_loss);
capacity->updateCapacity(I, params->dt_hr);
}

Expand Down Expand Up @@ -772,8 +782,12 @@ double battery_t::calculate_loss(double power, size_t lifetimeIndex) {
}
}

double battery_t::getLoss() {
return losses->getLoss();
double battery_t::getAncillaryLoss() {
return losses->getAncillaryLoss();
}

double battery_t::getAvailabilityLoss(size_t lifetimeIndex) {
return losses->getAvailabilityLoss(lifetimeIndex);
}

battery_state battery_t::get_state() { return *state; }
Expand Down
21 changes: 15 additions & 6 deletions shared/lib_battery.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ class thermal_t {
*/

struct losses_state {
double loss_kw;
double ancillary_loss_kw;
double adjust_loss_percent;

friend std::ostream &operator<<(std::ostream &os, const losses_state &p);
};
Expand All @@ -166,6 +167,7 @@ struct losses_params {
std::vector<double> monthly_discharge_loss;
std::vector<double> monthly_idle_loss;
std::vector<double> schedule_loss;
std::vector<double> adjust_loss;

friend std::ostream &operator<<(std::ostream &os, const losses_params &p);
};
Expand All @@ -181,17 +183,19 @@ class losses_t {
* \param[in] monthly_charge vector (size 1 for annual or 12 for monthly) containing battery system losses when charging (kW) (applied to PV or grid)
* \param[in] monthly_discharge vector (size 1 for annual or 12 for monthly) containing battery system losses when discharge (kW) (applied to battery power)
* \param[in] monthly_idle vector (size 1 for annual or 12 for monthly) containing battery system losses when idle (kW) (applied to PV or grid)
* \param[in] adjust_losses vector (size 0 for constant or per timestep) containing battery system availability losses (%) (applies to both power and energy capacity - if a system has 4 packs, a 25% loss means one pack is offline)
*/
losses_t(const std::vector<double>& monthly_charge, const std::vector<double>& monthly_discharge, const std::vector<double>& monthly_idle);
losses_t(const std::vector<double>& monthly_charge, const std::vector<double>& monthly_discharge, const std::vector<double>& monthly_idle, const std::vector<double>& adjust_losses);

/**
* \function losses_t
*
* Construct the losses object for schedule of timeseries losses
*
* \param[in] schedule_loss vector (size 0 for constant or per timestep) containing battery system losses
* \param[in] adjust_losses vector (size 0 for constant or per timestep) containing battery system availability losses (%) (applies to both power and energy capacity - if a system has 4 packs, a 25% loss means one pack is offline)
*/
explicit losses_t(const std::vector<double>& schedule_loss = std::vector<double>(1, 0));
explicit losses_t(const std::vector<double>& schedule_loss = std::vector<double>(1, 0), const std::vector<double>& adjust_losses = std::vector<double>(1,0));

explicit losses_t(std::shared_ptr<losses_params> p);

Expand All @@ -203,7 +207,9 @@ class losses_t {
void run_losses(size_t lifetimeIndex, double dt_hour, double charge_operation);

/// Get the loss at the specified simulation index (year 1)
double getLoss();
double getAncillaryLoss();

double getAvailabilityLoss(size_t lifetimeIndex);

losses_state get_state();

Expand Down Expand Up @@ -362,7 +368,7 @@ class battery_t {
double estimateCycleDamage();

// Run a component level model
void runCapacityModel(double &I);
void runCapacityModel(double &I, size_t lifetimeIndex);

void runVoltageModel();

Expand Down Expand Up @@ -409,7 +415,10 @@ class battery_t {
double calculate_loss(double power, size_t lifetimeIndex);

// Get the losses at the current step
double getLoss();
double getAncillaryLoss();

// Get the adjust loss at the current timestep
double getAvailabilityLoss(size_t lifetimeIndex);

battery_state get_state();

Expand Down
48 changes: 42 additions & 6 deletions shared/lib_battery_capacity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,16 +140,19 @@ capacity_params capacity_t::get_params() { return *params; }
capacity_state capacity_t::get_state() { return *state; }

void capacity_t::check_SOC() {
double q_upper = state->qmax_lifetime * params->maximum_SOC * 0.01;
double q_lower = state->qmax_lifetime * params->minimum_SOC * 0.01;
double max_SOC_available = params->maximum_SOC * (1 - state->percent_unavailable);
double min_SOC_available = params->minimum_SOC * (1 - state->percent_unavailable);

double q_upper = state->qmax_lifetime * max_SOC_available * 0.01;
double q_lower = state->qmax_lifetime * min_SOC_available * 0.01;

// set capacity to upper thermal limit
if (q_upper > state->qmax_thermal * params->maximum_SOC * 0.01) {
q_upper = state->qmax_thermal * params->maximum_SOC * 0.01;
if (q_upper > state->qmax_thermal * max_SOC_available * 0.01) {
q_upper = state->qmax_thermal * max_SOC_available * 0.01;
}
// do this so battery can cycle full depth and we calculate correct SOC min
if (q_lower > state->qmax_thermal * params->minimum_SOC * 0.01) {
q_lower = state->qmax_thermal * params->minimum_SOC * 0.01;
if (q_lower > state->qmax_thermal * min_SOC_available * 0.01) {
q_lower = state->qmax_thermal * min_SOC_available * 0.01;
}

if (state->q0 > q_upper + tolerance) {
Expand All @@ -175,6 +178,7 @@ void capacity_t::check_SOC() {
}

void capacity_t::update_SOC() {
// Want to continue to define SOC as nameplate minus degradation (availability losses lower SOC, not nameplate)
double max = fmin(state->qmax_lifetime, state->qmax_thermal);
if (max == 0) {
state->q0 = 0;
Expand Down Expand Up @@ -282,6 +286,8 @@ void capacity_kibam_t::replace_battery(double replacement_percent) {
state->leadacid.q2_0 = state->q0 - state->leadacid.q1_0;
state->SOC = params->initial_SOC;
state->SOC_prev = 50;
state->percent_unavailable = 0.0;
state->percent_unavailable_prev = 0.0;
update_SOC();
}

Expand Down Expand Up @@ -438,6 +444,22 @@ void capacity_kibam_t::updateCapacityForLifetime(double capacity_percent) {
update_SOC();
}

void capacity_kibam_t::updateCapacityForAvailability(double availability_percent) {
state->percent_unavailable_prev = state->percent_unavailable;
state->percent_unavailable = availability_percent;

double timestep_loss = state->percent_unavailable_prev - state->percent_unavailable;
if (timestep_loss > 1e-7) {
double q0_orig = state->q0;
state->q0 *= (1 - timestep_loss);
state->leadacid.q1 *= (1 - timestep_loss);
state->leadacid.q2 *= (1 - timestep_loss);
state->I_loss += (q0_orig - state->q0) / params->dt_hr;
}

update_SOC();
}

double capacity_kibam_t::q1() { return state->leadacid.q1_0; }

double capacity_kibam_t::q2() { return state->leadacid.q2_0; }
Expand Down Expand Up @@ -533,6 +555,20 @@ void capacity_lithium_ion_t::updateCapacityForLifetime(double capacity_percent)
update_SOC();
}

void capacity_lithium_ion_t::updateCapacityForAvailability(double availability_percent) {
state->percent_unavailable_prev = state->percent_unavailable;
state->percent_unavailable = availability_percent;

double timestep_loss = state->percent_unavailable - state->percent_unavailable_prev;
if (timestep_loss > 1e-7) {
double q0_orig = state->q0;
state->q0 *= (1 - timestep_loss);
state->I_loss += (q0_orig - state->q0) / params->dt_hr;
}

update_SOC();
}

double capacity_lithium_ion_t::q1() { return state->q0; }

double capacity_lithium_ion_t::q10() { return state->qmax_lifetime; }
8 changes: 8 additions & 0 deletions shared/lib_battery_capacity.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ struct capacity_state {
double I_loss; // [A] - Lifetime and thermal losses
double SOC; // [%] - State of Charge
double SOC_prev; // [%] - previous step
double percent_unavailable; // [%] - Percent of system that is down
double percent_unavailable_prev; // [%] - Percent of system that was down last step

enum {
CHARGE, NO_CHARGE, DISCHARGE
Expand Down Expand Up @@ -120,6 +122,8 @@ class capacity_t {

virtual void replace_battery(double replacement_percent) = 0;

virtual void updateCapacityForAvailability(double availability_percent) = 0;

void change_SOC_limits(double min, double max) {
params->minimum_SOC = min;
params->maximum_SOC = max;
Expand Down Expand Up @@ -199,6 +203,8 @@ class capacity_kibam_t : public capacity_t {

void replace_battery(double replacement_percent) override;

void updateCapacityForAvailability(double availability_percent) override;

double q1() override; // Available charge
double q2(); // Bound charge
double q10() override; // Capacity at 10 hour discharge rate
Expand Down Expand Up @@ -254,6 +260,8 @@ class capacity_lithium_ion_t : public capacity_t {

void replace_battery(double replacement_percent) override;

void updateCapacityForAvailability(double availability_percent) override;

double q1() override; // Available charge
double q10() override; // Capacity at 10 hour discharge rate
};
Expand Down
Loading

0 comments on commit b241d0e

Please sign in to comment.