Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions ssc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ set(SSC_SRC
cmod_annualoutput.cpp
cmod_battery.cpp
cmod_battery.h
cmod_battery_eqns.cpp
cmod_battery_eqns.h
cmod_battery_stateful.cpp
cmod_battery_stateful.h
cmod_battwatts.cpp
Expand Down
99 changes: 99 additions & 0 deletions ssc/cmod_battery_eqns.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/**
BSD-3-Clause
Copyright 2019 Alliance for Sustainable Energy, LLC
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, CONTRIBUTORS, UNITED STATES GOVERNMENT OR UNITED STATES
DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, 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 "cmod_battery_eqns.h"

#include "core.h"
#include "vartab.h"

#include <cmath>

bool Size_batterystateful(ssc_data_t data) {
auto vt = static_cast<var_table*>(data);
char errmsg[250];
if (!vt) {
return false;
}

double nominal_energy, desired_voltage, desired_capacity;

vt_get_number(vt, "nominal_energy", &nominal_energy);
vt_get_number(vt, "desired_voltage", &desired_voltage);
vt_get_number(vt, "desired_capacity", &desired_capacity);

// Cannot specify energy of zero (less than mW, really) due to resulting errors in scaling factors
if (nominal_energy < 1e-7) {
sprintf(errmsg, "nominal_energy cannot be less than 1e-7. Current value: %f", nominal_energy);
vt->assign("error", std::string(errmsg));
return false;
}

if (desired_capacity < 1e-7) {
sprintf(errmsg, "desired_capacity cannot be less than 1e-7. Current value: %f", desired_capacity);
vt->assign("error", std::string(errmsg));
return false;
}

vt->assign("original_capacity", nominal_energy);

bool thermal_success = Calculate_thermal_params(data);

vt->assign("nominal_energy", desired_capacity);
vt->assign("nominal_voltage", desired_voltage);

return thermal_success;
}

bool Calculate_thermal_params(ssc_data_t data) {
auto vt = static_cast<var_table*>(data);
if (!vt) {
return false;
}

double mass, surface_area, original_capacity, desired_capacity, module_capacity, module_surface_area;

vt_get_number(vt, "mass", &mass);
vt_get_number(vt, "surface_area", &surface_area);
vt_get_number(vt, "original_capacity", &original_capacity);
vt_get_number(vt, "desired_capacity", &desired_capacity);

double mass_per_specific_energy = mass / original_capacity;
Copy link
Collaborator

Choose a reason for hiding this comment

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

There is an edge case where the original_capacity is 0 and then resized to non-zero. This happens when you size the battery to 0, perhaps as part of a loop across a range of numbers, then the mass and surface area will get set to 0 also. Then for later sizing calls, the function will no longer be able to use prior information about the mass to calculate an appropriate mass, and here it'll cause a divide by 0.

Other cmods are not able to run with a strictly 0 system capacity (pvsamv1, windpower) while others can (pvwatts). While this is a still-unfixed issue in the PySAM code, I think the simplest way to handle this is to not let the desired_capacity be 0.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Great point! In the latest commit I used the same error convention as cmod_windpower_eqns - writing the error to an "error" variable in the vartable. Am I correct to assume it's the responsibility of the calling code to check this value? When I tried to throw an exec error, it crashed Julia. Given the difficulty of error handling in the SDK, I assume that's not a valid option.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, you can't throw exceptions across a DLL boundary so that's not possible. The error will have to be done via a return string. Perhaps we could change the function signature of SSC equations so the return type is bool instead of void. I don't think that would be too difficult and would make error handling easier

Copy link
Collaborator

@dguittet dguittet Oct 7, 2021

Choose a reason for hiding this comment

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

Let me know if you want me to change the function signature to bool. Otherwise you have to check if error len > 0

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That would be super helpful. I tried to do the update just now and ran into a type issue:

Severity Code Description Project File Line Suppression State
Error C2440 'initializing': cannot convert from 'bool (__cdecl *)(ssc_data_t)' to 'ssc_equation_ptr' (compiling source file C:\Users\bmirletz\source\repos\sam_dev\ssc\ssc\core.cpp) ssc C:\Users\bmirletz\source\repos\sam_dev\ssc\ssc\ssc_equations.h 87

It looks like we either need to change them all or define a new signature with bool. I changed the battery stateful equations in the most recent push to get that error, if you're able to do the others I'd appreciate it.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Apologies for the delay, but I've fixed up all the equations: changing the return type, fixing up the error handling from exceptions to error strings.


double volume = std::pow((surface_area / 6.0), (3.0 / 2.0));

double volume_per_specific_energy = volume / original_capacity;

mass = mass_per_specific_energy * desired_capacity;

surface_area = std::pow((volume_per_specific_energy * desired_capacity), (2.0 / 3.0)) * 6;

if (vt->is_assigned("module_capacity") && vt->is_assigned("module_surface_area")) {
vt_get_number(vt, "module_capacity", &module_capacity);
vt_get_number(vt, "module_surface_area", &module_surface_area);
surface_area = module_surface_area * desired_capacity / module_capacity;
}

vt->assign("mass", mass);
vt->assign("surface_area", surface_area);

return true;
}

65 changes: 65 additions & 0 deletions ssc/cmod_battery_eqns.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
BSD-3-Clause
Copyright 2019 Alliance for Sustainable Energy, LLC
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, CONTRIBUTORS, UNITED STATES GOVERNMENT OR UNITED STATES
DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, 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_BATTERY_EQNS_H_
#define _CMOD_BATTERY_EQNS_H_

#include "sscapi.h"

#ifdef __cplusplus
extern "C" {
#endif

static const char* size_batterystateful_doc =
"Resizes the battery for a battery_stateful data object \\n\\n"
"Input: var_table with key-value pairs\\n"
" 'nominal_energy': double [kWh]\\n"
" 'desired_capacity': double [kWh]\\n"
" 'desired_voltage': double [V]\\n"
" 'mass': double [kg] \\n"
" 'surface_area': double [m^2],\\n"
" 'module_capacity': double [kWh], optional\\n"
" 'module_surface_area': double [m^2], optional\\n"
"Output: key-value pairs added to var_table, mass, surface_area, and nominal_energy will be modified\\n"
" 'original_capacity': kWh [kWh]\\n";


SSCEXPORT bool Size_batterystateful(ssc_data_t data);

static const char* calculate_thermal_params_doc =
"Resizes the battery for a battery_stateful data object \\n\\n"
"Input: var_table with key-value pairs\\n"
" 'original_capacity': double [kWh]\\n"
" 'desired_capacity': double [kWh]\\n"
" 'mass': double [kg] \\n"
" 'surface_area': double [m^2],\\n"
" 'module_capacity': double [kWh], optional\\n"
" 'module_surface_area': double [m^2], optional\\n"
"Output: mass and surface_area will be modified\\n";

SSCEXPORT bool Calculate_thermal_params(ssc_data_t data);

#ifdef __cplusplus
}
#endif

#endif
39 changes: 23 additions & 16 deletions ssc/cmod_csp_tower_eqns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma warning(disable: 4297) // ignore warning: 'function assumed not to throw an exception but does'


void MSPT_System_Design_Equations(ssc_data_t data)
bool MSPT_System_Design_Equations(ssc_data_t data)
{
auto vt = static_cast<var_table*>(data);
if (!vt) {
throw std::runtime_error("ssc_data_t data invalid");
return false;
}
double P_ref, gross_net_conversion_factor, nameplate, design_eff, solarm, q_pb_design, q_rec_des, tshours, tshours_sf;

Expand All @@ -60,13 +60,14 @@ void MSPT_System_Design_Equations(ssc_data_t data)
ssc_data_t_get_number(data, "solarm", &solarm);
tshours_sf = Tshours_sf(tshours, solarm);
ssc_data_t_set_number(data, "tshours_sf", tshours_sf);
return true;
}

void Tower_SolarPilot_Solar_Field_Equations(ssc_data_t data)
bool Tower_SolarPilot_Solar_Field_Equations(ssc_data_t data)
{
auto vt = static_cast<var_table*>(data);
if (!vt) {
throw std::runtime_error("ssc_data_t data invalid");
return false;
}
double land_max, h_tower, land_max_calc, helio_height, helio_width, dens_mirror, csp_pt_sf_heliostat_area,
land_min, land_min_calc, csp_pt_sf_fixed_land_area, land_area_base,
Expand Down Expand Up @@ -95,7 +96,7 @@ void Tower_SolarPilot_Solar_Field_Equations(ssc_data_t data)
ssc_data_t_get_number(data, "dens_mirror", &dens_mirror);
csp_pt_sf_heliostat_area = Csp_pt_sf_heliostat_area(helio_height, helio_width, dens_mirror);
ssc_data_t_set_number(data, "csp.pt.sf.heliostat_area", csp_pt_sf_heliostat_area);

// This one is not being read in the UI
//// csp_pt_sf_total_reflective_area
//double csp_pt_sf_total_reflective_area;
Expand Down Expand Up @@ -129,7 +130,7 @@ void Tower_SolarPilot_Solar_Field_Equations(ssc_data_t data)
ssc_data_t_get_number(data, "a_sf_ui", &a_sf_ui);
helio_area_tot = Helio_area_tot(a_sf_ui);
ssc_data_t_set_number(data, "helio_area_tot", helio_area_tot);

// csp_pt_sf_tower_height
ssc_data_t_get_number(data, "h_tower", &h_tower);
csp_pt_sf_tower_height = Csp_pt_sf_tower_height(h_tower);
Expand Down Expand Up @@ -177,13 +178,14 @@ void Tower_SolarPilot_Solar_Field_Equations(ssc_data_t data)
dni_des_calc = Dni_des_calc(dni_des);
ssc_data_t_set_number(data, "dni_des_calc", dni_des_calc);

return true;
}

void MSPT_Receiver_Equations(ssc_data_t data)
bool MSPT_Receiver_Equations(ssc_data_t data)
{
auto vt = static_cast<var_table*>(data);
if (!vt) {
throw std::runtime_error("ssc_data_t data invalid");
return false;
}
double csp_pt_rec_max_oper_frac, q_rec_des, csp_pt_rec_htf_c_avg, t_htf_hot_des, t_htf_cold_des,
csp_pt_rec_max_flow_to_rec, csp_pt_rec_htf_t_avg, d_rec, rec_height, rec_aspect,
Expand Down Expand Up @@ -264,13 +266,14 @@ void MSPT_Receiver_Equations(ssc_data_t data)
ssc_data_t_get_number(data, "piping_loss", &piping_loss);
piping_loss_tot = Piping_loss_tot(piping_length, piping_loss);
ssc_data_t_set_number(data, "piping_loss_tot", piping_loss_tot);
return true;
}

void MSPT_System_Control_Equations(ssc_data_t data)
bool MSPT_System_Control_Equations(ssc_data_t data)
{
auto vt = static_cast<var_table*>(data);
if (!vt) {
throw std::runtime_error("ssc_data_t data invalid");
return false;
}
double bop_par, bop_par_f, bop_par_0, bop_par_1, bop_par_2, p_ref, csp_pt_par_calc_bop,
aux_par, aux_par_f, aux_par_0, aux_par_1, aux_par_2, csp_pt_par_calc_aux,
Expand Down Expand Up @@ -321,13 +324,14 @@ void MSPT_System_Control_Equations(ssc_data_t data)
wlim_series = Wlim_series(disp_wlim_max);
ssc_data_t_set_array(data, "wlim_series", wlim_series.data(), (int)wlim_series.ncells());
}
return true;
}

void Tower_SolarPilot_Capital_Costs_MSPT_Equations(ssc_data_t data)
bool Tower_SolarPilot_Capital_Costs_MSPT_Equations(ssc_data_t data)
{
auto vt = static_cast<var_table*>(data);
if (!vt) {
throw std::runtime_error("ssc_data_t data invalid");
return false;
}

double d_rec, rec_height, receiver_type_double, csp_pt_cost_receiver_area,
Expand Down Expand Up @@ -374,13 +378,14 @@ void Tower_SolarPilot_Capital_Costs_MSPT_Equations(ssc_data_t data)
ssc_data_t_set_number(data, "csp.pt.cost.power_block_mwe", csp_pt_cost_power_block_mwe);

Tower_SolarPilot_Capital_Costs_Equations(data);
return true;
}

void Tower_SolarPilot_Capital_Costs_DSPT_Equations(ssc_data_t data)
bool Tower_SolarPilot_Capital_Costs_DSPT_Equations(ssc_data_t data)
{
auto vt = static_cast<var_table*>(data);
if (!vt) {
throw std::runtime_error("ssc_data_t data invalid");
return false;
}

double d_rec, rec_height, receiver_type, rec_d_spec, csp_pt_cost_receiver_area,
Expand Down Expand Up @@ -413,13 +418,14 @@ void Tower_SolarPilot_Capital_Costs_DSPT_Equations(ssc_data_t data)
ssc_data_t_set_number(data, "csp.pt.cost.power_block_mwe", csp_pt_cost_power_block_mwe);

Tower_SolarPilot_Capital_Costs_Equations(data);
return true;
}

void Tower_SolarPilot_Capital_Costs_ISCC_Equations(ssc_data_t data)
bool Tower_SolarPilot_Capital_Costs_ISCC_Equations(ssc_data_t data)
{
auto vt = static_cast<var_table*>(data);
if (!vt) {
throw std::runtime_error("ssc_data_t data invalid");
return false;
}

double d_rec, rec_height, receiver_type, rec_d_spec, csp_pt_rec_cav_ap_height, csp_pt_cost_receiver_area,
Expand Down Expand Up @@ -453,4 +459,5 @@ void Tower_SolarPilot_Capital_Costs_ISCC_Equations(ssc_data_t data)
ssc_data_t_set_number(data, "csp.pt.cost.power_block_mwe", csp_pt_cost_power_block_mwe);

Tower_SolarPilot_Capital_Costs_Equations(data);
return true;
}
14 changes: 7 additions & 7 deletions ssc/cmod_csp_tower_eqns.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ extern "C" {
" 'Q_rec_des' - double [MWt]\\n"
" 'tshours_sf' - double [hr]";

SSCEXPORT void MSPT_System_Design_Equations(ssc_data_t data);
SSCEXPORT bool MSPT_System_Design_Equations(ssc_data_t data);


static const char* Tower_SolarPilot_Solar_Field_Equations_doc =
Expand Down Expand Up @@ -88,7 +88,7 @@ extern "C" {
" 'opt_flux_penalty' - double [-]\\n"
" 'q_design' - double [MWt]\\n";

SSCEXPORT void Tower_SolarPilot_Solar_Field_Equations(ssc_data_t data);
SSCEXPORT bool Tower_SolarPilot_Solar_Field_Equations(ssc_data_t data);


static const char* MSPT_Receiver_Equations_doc =
Expand Down Expand Up @@ -119,7 +119,7 @@ extern "C" {
" 'piping_loss_tot' - double [kWt]\\n"
" 'rec_aspect' - double [-]\\n";

SSCEXPORT void MSPT_Receiver_Equations(ssc_data_t data);
SSCEXPORT bool MSPT_Receiver_Equations(ssc_data_t data);


static const char* MSPT_System_Control_Equations_doc =
Expand All @@ -144,7 +144,7 @@ extern "C" {
" 'disp_wlim_max' - double [MWe]\\n"
" 'wlim_series' - double [kWe]\\n";

SSCEXPORT void MSPT_System_Control_Equations(ssc_data_t data);
SSCEXPORT bool MSPT_System_Control_Equations(ssc_data_t data);


static const char* Tower_SolarPilot_Capital_Costs_MSPT_Equations_doc =
Expand Down Expand Up @@ -205,7 +205,7 @@ extern "C" {
" 'total_installed_cost' - double [$]\\n"
" 'csp_pt_cost_installed_per_capacity' - double [$]\\n";

SSCEXPORT void Tower_SolarPilot_Capital_Costs_MSPT_Equations(ssc_data_t data);
SSCEXPORT bool Tower_SolarPilot_Capital_Costs_MSPT_Equations(ssc_data_t data);


static const char* Tower_SolarPilot_Capital_Costs_DSPT_Equations_doc =
Expand Down Expand Up @@ -261,7 +261,7 @@ extern "C" {
" 'total_installed_cost' - double [$]\\n"
" 'csp_pt_cost_installed_per_capacity' - double [$]\\n";

SSCEXPORT void Tower_SolarPilot_Capital_Costs_DSPT_Equations(ssc_data_t data);
SSCEXPORT bool Tower_SolarPilot_Capital_Costs_DSPT_Equations(ssc_data_t data);


static const char* Tower_SolarPilot_Capital_Costs_ISCC_Equations_doc =
Expand Down Expand Up @@ -319,7 +319,7 @@ extern "C" {
" 'total_installed_cost' - double [$]\\n"
" 'csp_pt_cost_installed_per_capacity' - double [$]\\n";

SSCEXPORT void Tower_SolarPilot_Capital_Costs_ISCC_Equations(ssc_data_t data);
SSCEXPORT bool Tower_SolarPilot_Capital_Costs_ISCC_Equations(ssc_data_t data);

#ifdef __cplusplus
}
Expand Down
Loading